OSF DCE SIG | H. Melman (OSF) | |
Request For Comments: 17.0 | December 1992 |
A goal of DCE Release 1.1 is to improve portability by responding to issues raised by DCE engineers and DCE licensees. This RFC examines these issues. Emphasis in this list has been placed on items that have actually made DCE code difficult to port in the past. The DCE SIG (Special Interest Group) was surveyed in order to identify as many code clean-up issues as possible, and the results of that survey will be noted as occasion arises throughout this document.
The intended audience of this RFC is those familiar with DCE code. This RFC is not meant as a cookbook with all details of how to change old code or write new code meeting DCE 1.1 standards. It is meant to provide enough information to determine what existing code needs to be changed, and to some extents the scope of those changes. For example, in the Use stronger compiler switches section below, this RFC states that more compiler switches will be used, and lists all possible ones, but does not specify the set of switches that will be used, merely that the set will be determined by OSF. Complete details are specified wherever possible.
The list of requirements is fairly long. The requirements are grouped into similar categories. Within each category they are generally listed from highest priority to lowest priority. This is not to mean that only some of these are requirements, merely that it is recognized that some are more important than others.
This section lists work items that are expected to be completed for DCE 1.1. Some of the items are required for both existing and new code, others for just new code. This is specified in each item.
DCE 1.1 will require an ANSI C compiler (see [ANSI C]) (except, names will be unique to 31 characters, not 8 characters). There will no longer be guaranteed support for the original Kernighan and Ritchie C [K&R]. Existing support may be left in the code; however, if it is not removed, it must be modified to use a single DCE-wide mechanism defined in \*(sBdce.h\*(sE (see Appendix below for a description of \*(sBdce.h\*(sE). Some mechanisms are currently defined in \*(sBdce.h\*(sE, any others required must be added to \*(sBdce.h\*(sE with OSF approval.
OSF/1, running on a specified platform, will serve as one of the DCE 1.1 reference platforms. On that platform \*(sBgcc\*(sE will be the compiler used, with the \*(sB-ansi\*(sE switch. In addition, other switches will be turned on to indicate additional warnings which must be fixed in the DCE code.\*(f!
An exception is any kernel code which will follow the conventions of the kernel build environment. Any C code generated by \*(sBidl\*(sE or \*(sBmavros\*(sE must also be ANSI C compliant and is subject to the same requirements as other DCE code.
The complete list of \*(sBgcc\*(sE version 2.0 warning switches is given below from the \*(sBgcc\*(sE documentation [GCC2]. The \*(sB-pedantic\*(sE switch (which must be used with the \*(sB-ansi\*(sE switch) does not add as much checking as one might think. It will be used, but others must be used as well. The \*(sB-Wall\*(sE switch implies all other switches in the column above it.
.ft 5
The list of switches used will be determined by OSF after some experience with \*(sBgcc\*(sE version 2.0 is obtained.\*(f! All
\*(sBgcc\*(sE version 2.0 will probably be used for DCE 1.0.2.switches will be tried, however there may be problems using some of them. For example, there is a possibility that the use of the \*(sBTRY\*(sE and \*(sBCATCH\*(sE macros of the CMA exception handling interface will always generate a warning detected by the \*(sB-Wuninitialized\*(sE switch. If there are problems with a particular switch and the problem is not fixable, then either the switch will be turned off, or the warnings from those cases will be ignored.
ANSI C requires the macro \*(sB__STDC__\*(sE be defined by the compiler. However, many compilers only define it in a strict ANSI mode, or support a subset of ANSI C features. Some DCE code makes use of explicit checks to see if \*(sB__STDC__\*(sE is defined to determine if a feature of ANSI C is to be used. These must either be removed completely, and the ANSI feature assumed to be present, or they must be changed to use a feature-specific macro defined in \*(sBdce.h\*(sE. This must be done for all existing and new code.
For example, the use of prototypes will be set on the flag \*(sB_DCE_PROTO_\*(sE, which will be set in \*(sBdce.h\*(sE. DCE code may not check if \*(sB__STDC__\*(sE is set to turn a prototype on or off. See the section Function prototypes in the Style Guide Appendix of this RFC for details.
Currently there are only two known uses of the \*(sB__STDC__\*(sE macro; to check for prototypes and for void pointers. Any other uses must be changed as well.
In addition to supporting ANSI C, DCE 1.1 will require prototypes for all functions.\*(f! No
An exception is any kernel code which will follow the conventions of the kernel build environment. It is not required that C code generated by \*(sBidl\*(sE or \*(sBmavros\*(sE contain function prototypes for all functions, however this should be a goal for future development work as resources allow.variable names are to be used in prototypes since they are subject to macro expansion.
All function definitions will use the new style function definition format as defined in ANSI C. For example:
.ft 5
becomes:
.ft 5
This is required as there are slightly different semantics associated with the two forms. If the old form is used, all arguments are subject to promotion, in the new form, the compiler is not required to perform the promotion for performance reasons. For this reason using, a prototype with an old-style function declaration can lead to problems with arguments that are subject to promotion.
The current use of a prototype macro as a selection method will not be required. However there will be one prototype macro defined in \*(sBdce.h\*(sE that can be used if desired. The use of all other prototype macros in existing or new code must either be removed or changed to this macro. It is described in the Style Guide Appendix of this RFC. It was chosen since it is very similar to the macro used in CMA, RPC, CDS, and GDS. DTS currently uses a macro of a different form.
To restate the requirement, all functions must use prototypes and new-style function definitions. Support for old-style function definitions can be included, but must use the common DCE-wide macro.
All instances of \*(sB#ifdef\*(sE in both new and existing code must be ANSI C compliant. This means that there can be no text following a \*(sB#else\*(sE or \*(sB#endif\*(sE unless it is a comment. The following is illegal:
.ft 5
It should be changed as follows:
.ft 5
The text should not simply be removed. If the text is still correct, place it within comment delimiters.
Provider companies will be responsible to ensure that target machine dependencies are in fact target machine dependent. Code that can be isolated based on a feature such as endianess will be handled as follows:
.ft 5
That is, not in a target machine specific manner. One of \*(sBBIG_ENDIAN\*(sE or \*(sBLITTLE_ENDIAN\*(sE will be defined in \*(sBdce.h\*(sE. The solution and the different macros used must be documented in the DCE Porting and Testing Guide [PORTG].
All macros used in conditional compilation (i.e., \*(sBifdef\*(sEs) must be documented in the DCE Porting and Testing Guide. Provider companies are responsible for supplying this information to OSF so it can be documented.
The current list of supported target machines must be checked as well. The extra code needed to support non-references platforms often obfuscates the code. Support for non-DCE systems must be removed (e.g., DECNET) in both \*(sB#ifdef\*(sEs and in target machine specific subdirectories. It is believed that in DFS there are a lot of target machine and architecture conditionals that go back to platforms supported in AFS 3. These must be removed as well.
All remaining machine dependencies must be isolated and moved to machine dependent files. There will be no \*(sB#ifdef\*(sE in any existing or new DCE code to check what machine it is on. This will make porting to a new platform easier, particularly when dealing with updates. Every machine-dependent function will be in a machine-dependent file (preferably of the same name). These functions (both existing and new) must be documented in the DCE Porting and Testing Guide. This work will be done by provider companies.
There were many complaints about DCE code being inconsistent and having many duplicate definitions of functionality. A major complaint was that DCE seems to use every known system interface, making it difficult to port to some systems. The following requirements address these concerns.
Lack of centralization of DCE-wide definitions is a very common complaint about DCE 1.0. Much of the code that requires porting is spread throughout DCE, and often is duplicated. A new public header file, \*(sBdce.h\*(sE, will provided by OSF and will be included by most, if not all, DCE C source files. This file will include all typedefs, macro definitions, and possibly common includes, etc., that span components. It will be machine specific; it must be ported to each platform. OSF will own this file, providers are responsible for including it in their code.
See Appendix A in this RFC for the current version of \*(sBdce.h\*(sE for the PMAX platform. Providers who have typedefs, macros, prototypes, etc., that need to be included, must identify them for inclusion by OSF. Examples of typedefs and macros found in this header file include:
Also, other DCE-wide declarations such as serviceability macros and prototypes, and debugging macros will be obtained by a module by including \*(sBdce.h\*(sE.
It will be required that each component use these definitions where appropriate for all existing and new code. No duplication of functions in \*(sBdce.h\*(sE will occur in component header files. (This is what will simplify the porting effort. It would make no sense to have a standard set of definitions and still use others.)
One of the complaints about DCE is that it uses many different routines that do the same thing. In an effort to reduce this problem, DCE 1.1 defines the following hierarchy of standards to be used to determine the appropriate system or library routine to call. Much of this work will be accomplished during the SVR4 merge as part of DCE 1.0.2.
All new code must conform to the following. All existing code should as well, but where this is not practical, at a minimum all non-standard usages must be documented in the DCE Porting and Testing Guide.
All uses of the \*(sBvararg\*(sE facility to handle variable length argument lists must be changed to use the ANSI C defined \*(sBstdarg\*(sE facility. No support of the \*(sBvararg\*(sE facility will be in DCE 1.1 since its similarity with the \*(sBstdarg\*(sE facility can make it confusing for the reader. Provider companies will be responsible for doing any conversions necessary.
A utility library which would hide some of the utility/OS specific code from the rest of the system would aid in porting. OSF will provide (or approve) an implementation of the following items to be used by all DCE components.
OSF will create a new common library that will include the above mechanisms.
In order to make the DCE code easier to read and follow, all macro names defined by DCE will be in all upper-case. Providers are responsible for changing all existing code to follow this convention, and for ensuring all new code follows this convention. Macros that implement standard routines, will follow whatever conventions the standard requires (e.g., the pthreads routines defined by CMA must be in lower-case).
There are 58 different macros in DCE that have the text \*(sBDEBUG\*(sE in them. Some use positive logic, others negative to turn debugging on or off. Some are set only at compile time and others allow for runtime setting. A single mechanism, to be used across all DCE components, is specified as part of the DCE 1.1 serviceability project. It can be set on a component by component basis, at both compile time and at runtime, and will be obtained by including \*(sBdce.h\*(sE.
Debugging instructions will be activated if the macro \*(sBDCE_DEBUG\*(sE
is defined. Defining this one macro via ODE for all of DCE will turn on
all debugging statements. Further, individual components should define
this macro in an internal, component-wide header file, if a component debug
macro is defined. This must be done in an internal header file that other
components will not be including, or else setting debugging on for one
component could have an effect on another. This component debug macro is
\*(sBDCE_CMP
_DEBUG\*(sE, where \*(sBCMP
\*(sE is the three
letter acronym for the component in uppercase.\*(f! For
One of: \*(sBTHR\*(sE, \*(sBRPC\*(sE, \*(sBCDS\*(sE, \*(sBSEC\*(sE, \*(sBDTS\*(sE, \*(sBGDS\*(sE, \*(sBDFS\*(sE.example, the following should appear in a \*(sBcds.h\*(sE file:
.ft 5
All new and existing debug code must use or be changed to use this mechanism.
No DCE code should make any calls directly to CMA, Kerberos or any other inappropriate interface. An inappropriate interface is one which is not exported by the service for use by a DCE component. For example, \*(sBcma_*()\*(sE calls are not to be used by other components, \*(sBpthread_*()\*(sE calls should be used. Also, \*(sBcdspi_*()\*(sE calls are allowed to be called by the NSI (and XDS), but not by other components, they should use the NSI.
It is believed that DFS makes calls directly to Kerberos, and CDS makes calls directly to CMA. These need to be checked and fixed. Each component must be reviewed for the appropriateness of the calls it makes to other components in both existing and new code.
Presently, DCE relies upon a \*(sBuid\*(sE of \*(sB0\*(sE to determine appropriate (root) privilege (e.g., \*(sBsrc/security/server/rs/rs_main.c\*(sE). The [POSIX.1] standard does not prescribe that \*(sBuid 0\*(sE is the root or superuser. In fact, \*(sBuid 0\*(sE need not exist for POSIX compliance. Hence, the mechanism DCE employs to check for appropriate privilege, namely \*(sBsetuid(0)\*(sE and subsequent checks for \*(sBgeteuid() == 0\*(sE, may not suffice for some compliant POSIX systems. In fact, these will fail where a \*(sBuid\*(sE of \*(sB0\*(sE is not allowed/defined.
The following new functions will be defined, in a target machine specific module, to isolate these issues. All existing and new code must call these routines where appropriate.
.ft 5
Hence:
.ft 5
becomes:
.ft 5
And:
.ft 5
becomes:
.ft 5
It needs to be possible to change the DCE root directory without having to recompile nearly all the files. \*(sBDCE_LOCAL\*(sE will be a variable instead of a macro. It will not be an environment variable for security reasons.
The header file \*(sBdce.h\*(sE will declare a variable defined to give the path of the root of the dcelocal directory on the installed system. This is by default \*(sB/opt/dcelocal\*(sE:
.ft 5
All references to this path in both existing and new code must be determined by the use of this variable.
The control programs, as well as all other DCE programs, will use the termios interface from [POSIX.1] and [XPG4] as specified in the [AES] for handling terminal I/O. Again, a single interface used for this function will make the code easier to port. All code both existing and new must be changed to use these interfaces as opposed \*(sBioctl()\*(sE or anything else.
There were also some complaints about the usage of include files in DCE. Simple solutions to these problems are presented below.
There are places in DCE where system and library calls are prototyped, as opposed to the prototype being obtained by including a system header file. These must be removed and replaced with the appropriate \*(sB#include\*(sE in all existing and new code.
If systems do not properly define the prototypes in these header files, it is considered a machine specific problem and should be handled in a machine specific manner in \*(sBdce.h\*(sE or in another appropriate header file.
Most, if not all, DCE header files currently have some mechanism to prevent duplicate inclusion of the same header file. However, different mechanisms are used. It will be standardized in DCE 1.1 so that all header files, in both existing and new code, begin and end with:
.ft 5
where \*(sBHEADER\*(sE is the base name of the header file in uppercase.
Some files check \*(sBHEADER_INCLUDED\*(sE or some other macro. Ideally, checks should be done at the point of the inclusion instead of within the file to avoid having to read the whole file if it has already been included. This will not be required for DCE 1.1, but having consistently generated macros to check would facilitate such a change if a licensee deems it necessary.
Providers are responsible to check and if necessary change all headers so that they check for duplicate inclusion in the proper manner.
One response to the Code Clean-Up Survey was phrased very succinctly:
Build environment issues are all grouped in this section since typically they do not involve DCE code, but rather the makefiles and source tree organization.
There are some simple clean-up issues that need to be done:
When DCE is ported to OSF/1 1.1 the complicated method of building libdce on a PMAX can be removed and both the PMAX and RIOS can use the same method of getting the objects for libdce from the component libraries. This work will be done by OSF engineers.
All the components must be reviewed so that everything that is needed is placed in the install tree not the object tree. The tests are the worst offenders. The goal of a build is to populate the install tree, the object tree is just an intermediary point. The results of the build, including all executables, datafiles, scripts, and anything else needed to run DCE or the tests, will be in the install tree. This work will be done by DCE engineers at provider sites.
If an object is to be included in more than one executable it must be in a library. Any places where this is not true must be corrected in both existing and new code. This work will be done by provider companies.
DCE should be able to be built in a sandbox which is mounted via NFS. Currently this is not possible due to the way a database is created for GDS. This must be investigated and corrected if possible. This work is to be done by provider companies with support from the OSF Release and Tools Group.
The method of building the kernel used by DFS must be corrected so that the passes match as close as possible the passes used in other areas of the DCE build process. Currently each pass must be invoked by hand, they must be automated by ODE. This work will be done by the OSF Release and Tools Group.
The DCE common makefiles need to be cleaned up as well. There have been many complaints that they are too complicated. In addition, they need to be documented. These files define the variables used in DCE makefiles. The documentation must include a usage section, explaining how DCE makefiles should be written.
The OSF Release and Tools Group will be responsible for the clean up of the common makefiles and for the writing of this documentation. Provider companies must modify both existing and new makefiles to meet these guidelines. In general, this will mean makefile cleanup on the order of using the \*(sBCFLAGS\*(sE variable correctly, and the proper use of \*(sBINCFLAGS\*(sE.
The methods of handling machine dependencies in DCE are both varied and unwieldy. First of all a solution to the PMAX versus MIPS debate must be finalized. It will include how to differentiate between \*(sBTARGET_MACHINE\*(sE and \*(sBTARGET_OS\*(sE and even \*(sBTARGET_OS_VERSION\*(sE (how will differences between OSF/1 1.0 and OSF/1 1.1 be handled?). The OSF Release and Tools Group will be responsible for determining the solution to this problem. Provider companies will be responsible for the implementation.
The \*(sBcomponent.mk\*(sE files will be removed and replaced with \*(sBmachdep.mk\*(sE files. Currently all the components have a top level file which sets machine specific flags for each directory in the component, that is named with the name of the component followed by \*(sB.mk\*(sE, for example, \*(sBsrc/rpc/rpc.mk\*(sE. The result is that many (not all) of the machine specific flags are in one place. However, the build is longer since this lengthy file must be read every time that \*(sBmake\*(sE is invoked, porting is less clear since machine dependencies occur in \*(sBcomponent.mk\*(sE files, in the \*(sBosf.dce.mk\*(sE file, in the \*(sBMakeconf\*(sE file, in \*(sBmachdep.mk\*(sE files, in the \*(sBMakefile\*(sE, etc. These will be isolated so that there is one file with project wide machine specific settings (either \*(sBMakeconf\*(sE or \*(sBosf.dce.mk\*(sE) and then separate files with machine specific settings in each directory where needed. These \*(sBcomponent.mk\*(sE files were created to simplify porting, but they seem to have just made it more complicated. The OSF Release and Tools Group will be responsible for this work.
There shall be a rule for creating all stubs and headers from \*(sB\&.idl\*(sE files so that they are not built more than once as they currently are. This is one of the few things preventing DCE from using the parallel \*(sBmake\*(sE. The rule will create these files once, probably in their own pass after the headers are exported and before the libraries are exported (pass=SECOND?). It might involve a new switch to \*(sBidl\*(sE being created so that it can be run without generating a header file. Also, there are some places in DCE (e.g., Security) where the same \*(sB\&.idl\*(sE file is processed more than once with different \*(sB\&.acf\*(sE files so that the generated stubs are different. This must be done in an orderly way. The OSF Release and Tools Group will be responsible for determining the solution to this problem. Provider companies will implement the solution. Since the number of \*(sB\&.idl\*(sE files is small, this is not expected to be a large work item.
The build environment in DCE has been a problem for a long time. Two of the problems are the length of builds and the inability to do incremental builds. Incremental builds in DCE are rebuilds of all of DCE, in a sandbox that already contains a previously built DCE. Header file and library dependencies are not included in the makefiles, so if these are changed, it is up to the programmer to know what needs rebuilding. This is not always possible with a project the size of DCE, so full rebuilds are done. ODE has a tool called makedepend (\*(sBmd\*(sE) that can generate header files dependencies by parsing the C source files. The current method of building \*(sBlibdce\*(sE on a PMAX prohibits this from being run, but this will be corrected when DCE is ported to OSF/1 1.1. Library dependencies are important as well, but since these are less numerous and less mutable, they will be included by hand in the makefiles. \*(sBmd\*(sE works by building static files with dependencies, this is a process that will be run during a nightly build, so any changes in dependencies might not be immediately reflected in these dependency files. The OSF Release and Tools group will be responsible for this work.
Incremental builds are not the only problem. If the above is implemented, there is still a restriction that builds happen from the top \*(sBsrc\*(sE directory and be allowed to progress through all the subdirectories in each pass. This is because there are many unspecified inter-directory dependencies. One directory will assume that another directory has already been built and try to find objects there via the \*(sBVPATH\*(sE construct. This creates two problems. First, it is hard to rebuild one component (known as a partial build) since you might have to rebuild in another directory to get objects it depends on, and two, it makes debugging build problems more difficult. If you find that something did not build, you must find out from which directory it was trying to build, and from where it was trying to get sources. Use of the \*(sBVPATH\*(sE construct should be avoided, unfortunately there are 127 occurrences of it in the DCE makefiles. The solution to this problem is a tree reorganization.
This involves changing the tree structure of the DCE source tree including directory names and organization. The goal is to simplify the makefiles and allow partial builds. Many of the complexities come from the fact that there is more than one build target in most of the DCE directories. This exploited a bug in ODE for which the fix involved invoking \*(sBmake\*(sE once for every pass (there are 7 passes) in each directory, whether it is needed or not. It also makes the makefiles more complex since each make variable must be prepended with the target.
To solve this, the tree should be restructured in the following manner. (Much of this comes from a document describing the DME tree structure.)
A
\*(sE contains everything for library \*(sBA
\*(sE
\*(sBcomp/lib/libB
\*(sE contains everything for library \*(sBB
\*(sE
\*(sBcomp/foo
d\*(sE all sources for the \*(sBfoo
\*(sE daemon
\*(sBcomp/foo
cp\*(sE all sources for the \*(sBfoo
\*(sE control program
\*(sBcomp/foo
clerk\*(sE all sources for the \*(sBfoo
\*(sE clerk
Additional rules would include:
Certainly there are some aesthetic improvements as well. The code is more uniform and it is easier to find something in the tree. (How fast can you find \*(sBacl_edit\*(sE in the tree? It is not in \*(sBsrc/security/client/acl\*(sE as you might think, it is in \*(sBsrc/security/client/admin/acl_edit\*(sE. \*(sBsec_clientd\*(sE gets its own directory, but \*(sBsecd\*(sE is found in \*(sBsrc/security/server/bin\*(sE.)
Unfortunately, a tree reorganization would cause many problems for continuing development and perhaps for licensees. Before a decision can be made, a prototype will done. One component will be reorganized, the changes noted, and then the affected parties conferred with to determine the impact of such changes. OSF will prototype and make the decision based on cost, benefit, and resources. Providers should plan to convert to the new structure during DCE 1.1.
This section is derived mostly from responses received from the Code Clean-Up Survey. These items are specific to a particular component. Often they are restatements of other requirements, but are included here where a particular component requires more than general work to meet the requirement. Included here as well, are items received from the Code Clean-Up Survey that will not be requirements of DCE 1.1. These are clearly identified and are included for informational reasons only.
Requirements:
As a rule, do not define types via IDL and then send them over the net without going via marshalling / unmarshalling code -- doing this for rpc message headers would be a big expense, so in cases like that, do not use IDL defined types as part of the message headers.
Do not define system types via IDL and then pass them to system calls (e.g., \*(sBsockaddr_t\*(sE from \*(sBrpc/sys_idl/lbase.idl\*(sE, was a truly painful experience for some licensees).
.ft 5
.ft 5
.ft 5
Non-Requirements:
This is not a problem with code but rather documentation. There are hooks in the code to correct this problem. On those machines where the format of the \*(sBuuid_t\*(sE type will cause problems, code must be added in the \*(sB#ifdefs\*(sE marked with \*(sBMISPACKED_HEADER\*(sE. There are only twon or three places where this occurs. Porting instructions need to be added to the DCE Porting and Testing Guide.
Requirements:
The text from this item came from CR Number 5164 in the DCE OpenTrack database.
CDS is using one or more of the following \*(sBlibutc\*(sE routines: \*(sButc_strtorel()\*(sE, \*(sButc_strtouc()\*(sE, \*(sButc_mkutcstr()\*(sE, \*(sButc_mkrelstr()\*(sE. These routines are obsolete, and will be removed from \*(sBlibutc\*(sE. CDS is the only component using these routines. The supported routines are: \*(sButc_ascgmtime()\*(sE, \*(sButc_asclocaltime()\*(sE, \*(sButc_ascanytime()\*(sE, \*(sButc_ascreltime()\*(sE, \*(sButc_mkasctime()\*(sE, \*(sButc_mkascreltime()\*(sE.
The contents of \*(sBfcntl.h\*(sE are regulated by POSIX (assuming a POSIX-compliant machine) whereas the contents of \*(sBsys/file.h\*(sE are not. Some licensees, for example, has had several namespace conflicts because their version of \*(sBsys/file.h\*(sE defines some structures that DCE tried to redefine, like \*(sBthread_t\*(sE.
This problem has been most common in CDS and GDS. Here is a sample list of files (probably not exhaustive):
There are places in CDS, where a byte pointer is legally cast to a struct pointer and then dereferenced. This is perfectly legal in ANSI C, but ANSI C also allows this to result in the generation of an alignment error. The suggested solutions range from insert macro calls wherever this occurs in order to align the structure, to the cleaner, use RPC and its marshalling capabilities, that is what it is there for. This casting problem is very pervasive throughout the CDS code.
The extreme solution of converting everything to use the IDL generated \*(sBcds_\*(sE structures code rather than those in \*(sBdns_record.h\*(sE would allow:
It is not believed that it would involve a protocol change since these problems occur in the communication between the \*(sBlibcds\*(sE and the \*(sBcdsclerk\*(sE. The problem needs to be analyzed, a solution devised, and implemented.
Requirements:
Non-Requirements:
Requirements:
.ft 5
The first is used most consistently, and should be followed.
.ft 5
The following requirements are open ended. Transarc must address these issues and present work plans to OSF. OSF and Transarc must agree on what are satisfactory exit criteria for this work.
.ft 5
MACRO_BEGIN \e tkm_TokenID_INIT(&((dstP)->tokenID)); \e (dstP)->state = TKM_TOKEN_INIT; \e (dstP)->sleepers = 0; \e (dstP)->pendingRPCCount = 0; \e (dstP)->hostPossessingToken = (hostP); \e if ((dstP)->hostPossessingToken != (struct hs_host *)NULL) { \e (void)HS_HOLD((dstP)->hostPossessingToken); \e } \e (dstP)->expiration = 0L; \e (dstP)->timeQueued = 0L; \e tkm_TokenDomain_Init(&((dstP)->tknDomain)); \e (dstP)->nextP = (tkm_internalToken_p)NULL; \e (dstP)->prevP = (tkm_internalToken_p)NULL; \e (dstP)->headP = (struct tkm_tokenListHead *)NULL; \e \e if ((srcP) == (tkm_token_t *)NULL) { \e tkm_TokenSet_MAKE_EMPTY(&(dstP)->types); \e TKM_BYTERANGE_MAKE_RANGE_EMPTY(&((dstP)-> \e tknDomain.tokenBytes)); \e } \e else { \e tkm_TokenSet_COPY(&((dstP)->types), &((srcP)->type));\e hset64((dstP)->tknDomain.tokenBytes.lowBnd, \e (srcP)->startPositionExt, (srcP)->startPosition); \e hset64((dstP)->tknDomain.tokenBytes.upBnd, \e (srcP)->endPositionExt, (srcP)->endPosition);\e } \e MACRO_END
.ft 1
This section discusses items that were received as part of the Code Clean-Up Survey sent to the DCE SIG, but are not expected to be completed (or necessarily begun) in DCE 1.1.
This is not a requirement for DCE 1.1 since it would be very difficult for some providers to test their code for 16 or 64 bit cleanliness. OSF will certainly accept corrected code, and wherever possible will include it in DCE code or documentation.
Make use of analysis tools to determine the McCabe Complexity Metric of the code and simplify any code with too high a value. This work has been started here at OSF. DME has chosen 25 as the upper limit for acceptable code. Other experiences are that 10 is a better value. From a sample in July, 316 function in CDS (including some IDL generated code) had McCabe complexities above 10. This sounds worse than the situation really is. Many were machine generated functions, 167 were below 20 and 224 were below 25, but there is still real work to be done here.
Work of this nature is not considered Code Clean-Up but rather part of the Quality work scheduled for DCE 1.1.
The following is common in DCE code:
.ft 5
For some machines the use of slashes in the name of the include file could cause a problem. However, since many compilers on these machines can handle slashes in names, and since it would be a large effort to change all DCE existing code, this is not a requirement for DCE 1.1.
The \*(sBpasswd\*(sE structure in DCE (\*(sBpwd.h\*(sE) is based on BSD 4.3 and contains two fields (\*(sBpw_passwd\*(sE and \*(sBpw_gecos\*(sE) which are not defined by [POSIX.1]. Consequently, a compliant implementation of POSIX which is not required to support these fields, especially in the order defined in \*(sBpwd.h\*(sE, may produce unexpected results.
However, considering that many existing Unix systems, applications, and users rely upon the non-POSIX information in the \*(sBpasswd\*(sE structure, the following was proposed:
There is currently a defect\*(f!
See CR Number 5978 in the DCE OpenTrack database for details.open on this for DCE 1.0.2. It is scheduled to be fixed in DCE 1.0.2 by fixing the return of local OS data from sec_login to use platform dependent functions (as documented). The code will stop making any assumptions that a BSD 4.4 \*(sBpasswd\*(sE structure is used by the local system.
Unifying the syntax of the control programs would be very nice from a user's point of view. It certainly would make things more logical. However this is out of the bounds of code clean-up for DCE 1.1. It might be included in other work areas.
There is a suggestion to have \*(sBdce.h\*(sE do work to centralize the \*(sB#include\*(sEs of system header files. Where system header files are needed (e.g., for the flags used by \*(sBopen()\*(sE, \*(sBfseek()\*(sE, etc.) centralize the way they are included. One possible means of doing this is to have \*(sBdce.h\*(sE have sections along the lines of:
.ft 5
Then in the actual source files you have the following:
.ft 5
This would mean that only one place would need changing to get the correct header files for your operating system.
In order for common utilities to be mapped onto a single name, the same file could also do things like the following:
.ft 5
This suggestion would only be used in places where there are known machine differences, and if the methods described above in the Standardize System and Library Calls section do not result in finding an appropriate function to use.
This requirement is to determine a DCE style and to enforce it by running a pretty printer on all DCE sources. This will not make the code more portable, however, it will make it more consistent to read, which might be very important to licensees, particularly where one person is responsible for more than one component.
The major drawback of doing this to all DCE code is the effect it will have on tracking differences between versions of code as well as problems providers will have dealing with code in a new format. For these reasons this will not be done for DCE 1.1.
The items in this section require some further investigation or decision on their inclusion or exclusion from DCE 1.1 requirements. Issues raised in the Requirements section above are listed here for completeness.
In selecting code for a common dce utilities library, there are licensing issues when these routines are used in other components. It is common practice that providers use the same code tree for their DCE product as well as their proprietary product. All DCE code is subject to the DCE license, except that which providers already owned. The use of common utilities covered under a DCE license can make this more difficult.
It has been requested that the RCD Ids of files not be removed from the code to aid in version tracking of bug reports. It is common OSF practice to remove these Ids before shipping. Changing this practice will be investigated by OSF.
As recent 1.0.1 experience shows, DCE must provide better documentation on the locking schemes employed, both within each component and particularly between components. This documentation will go into the DCE Porting and Testing Guide. A simple layer above \*(sBpthread_mutex\*(sE calls could be implemented to enforce the lock hierarchy and aid in debugging.
Goals:
Non-goals:
The following is a sample version of \*(sBdce.h\*(sE for the PMAX platform. It is expected to be expanded.
.ft 5
/* * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, * Inc. ALL RIGHTS RESERVED (DCE). */ #if !defined(_DCE_H) #define _DCE_H /* * Common definitions for DCE * This is a machine specific file that must be ported to each * platform. */ /* * Define the endianess of the platform, either BIG_ENDIAN or * LITTLE_ENDIAN. * Definitions for byte order, by byte significance from low address * to high. * #define LITTLE_ENDIAN 1234 least-significant byte first * #define BIG_ENDIAN 4321 most-significant byte first */ #define LITTLE_ENDIAN /* Only one place needed for DCE to define these */ #define FALSE 0 #define TRUE 1 #if !defined(MIN) # define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #if !defined(MAX) # define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif /* * Machine dependent typedefs for boolean, byte, and (un)signed * integers. * All DCE code should be using these typedefs where applicable. * The following are defined in nbase.h: * unsigned8 unsigned 8 bit integer * unsigned16 unsigned 16 bit integer * unsigned32 unsigned 32 bit integer * signed8 signed 8 bit integer * signed16 signed 16 bit integer * signed32 signed 32 bit integer * Define the following from idl types in idlbase.h (which is * included by nbase.h): * byte unsigned 8 bits * boolean unsigned 8 bits */ #include <dce/nbase.h> typedef idl_byte byte; typedef idl_boolean boolean; /* * The following allows for the support of both old and new style * function definitions and prototypes. All DCE code is required to * be ANSI C compliant and to use prototypes. For those components * that wish to support old-style definitions, the following macros * must be used. * * Declare a prototype like this (don't use variables): * int foo _DCE_PROTOTYPE_((int, void *, struct bar *)) * * Define a function like this: * int foo * #if defined(_DCE_PROTO_) * ( * int a, * void *b, * struct bar *c * ) * #else * (a, b, c) * int a; * void *b; * struct bar *c; * #endif */ #if defined(__STDC__) /* other conditionals can be tested */ # define _DCE_PROTO_ #endif /* defined(__STDC__) */ #if defined(_DCE_PROTO_) # define _DCE_PROTOTYPE_(arg) arg #else /* defined(_DCE_PROTO_) */ # define _DCE_PROTOTYPE_(arg) () #endif /* defined(_DCE_PROTO_) */ /* * For those components wishing to support platforms where void * pointers are not available, they can use the following typedef for * a generic pointer type. If they are supporting such platforms * they must use this. */ #if defined(__STDC__) # define _DCE_VOID_ #endif /* defined(__STDC__) */ #if defined(_DCE_VOID_) typedef void * pointer_t; #else /* defined(_DCE_VOID_) */ typedef char * pointer_t; #endif /* defined(_DCE_VOID_) */ /* * Here is a macro that can be used to support token concatenation in * an ANSI and non-ANSI environment. Support of non-ANSI * environments is not required, but where done, this macro must be * used. */ #if defined(__STDC__) # define _DCE_TOKENCONCAT_ #endif #if defined(_DCE_TOKENCONCAT_) # define DCE_CONCAT(a, b) a ## b #else /* defined(_DCE_TOKENCONCAT_) */ # define DCE_CONCAT(a, b) a/**/b #endif /* defined(_DCE_TOKENCONCAT_) */ /* * Define the dcelocal directory, it will be "/opt/dcelocal * The variable is defined in dceldir.c */ extern char *dcelocaldir; /* If DCE_DEBUG is defined then debugging code is activated. */ #define DCE_DEBUG /* * Serviceability and perhaps other DCE-wide include files * will be included here. This is a sample only. */ #include <dce/dce_svc.h> #endif /* _DCE_H */
.ft 1
The goals of this section are to capture items received in response to the Code Cleanup-Up Survey, which are not requirements, but are still recommended; and to describe methods of implementing requirements. It is a first step towards a DCE Code Clean-Up Cookbook.
It has been suggested that comments following an \*(sB#else\*(sE and an \*(sB#endif\*(sE that describe the conditional be required in all DCE code. This will not be required for DCE 1.1 but is recommended.
There have been problems in DCE involving the differences between \*(sB#ifdef\*(sE and \*(sB#if\*(sE. An \*(sB#ifdef\*(sE test will return true if the value is defined, even if it is defined to be zero. An \*(sB#if\*(sE test will return true if the tokens evaluate to non-zero.
As a result of these problems and of problems when adding additional cases to an existing \*(sB#ifdef\*(sE, it has been suggested that \*(sB#ifdef\*(sE not be used at all in DCE and that it be replaced with the more explicit, C-like, clearer, and more easily extended:
.ft 5
This will not be required in DCE 1.1 code, as the difference is quite minor when adding conditionals, and \*(sB#ifdef\*(sE is quite different from \*(sB#if\*(sE. Mistakes that have been made confusing the two, could just as easily be made in including the \*(sBdefined()\*(sE in the \*(sB#if\*(sE.
It has also been requested that a nested \*(sB#ifdef\*(sE be indented to match the level of indentation. ANSI C allows spaces between the leading \*(sB#\*(sE (which must be in the leftmost column) and the token. The following is a common style of indentation:
.ft 5
While this style is recommended, it will not be required for DCE 1.1. It might make the code simpler to read, however, it does not aid in its portability. Also, there will be an effort to remove as many occurrences of \*(sB#ifdef\*(sE and \*(sB#if\*(sE in the code as possible, so it is expected that the above cases will occur infrequently.
Whenever possible indicate porting problems at compile time. This is most easily accomplished with the \*(sB#error\*(sE pre-processor command. For example, if a section of code is dependent on a feature macro that needs to be defined in \*(sBdce.h\*(sE a conditional test before its use is appropriate:
.ft 5
The following prototype macro will be defined in \*(sBdce.h\*(sE and needs to be used for all functions that wish to support old-style function definitions. Support of old-style function definitions is not required, but if it is included in the code it must be done using the following macro definitions.
.ft 5
It is used in the following manner:
.ft 5
This is very similar to the macros currently used by the CMA, RPC, and CDS components. A simple \*(sBsed\*(sE script could be run to change those components to use these macros.
Howard Melman | Internet email: melman@osf.org | |
Open Software Foundation | Telephone: +1-617-621-8989 | |
11 Cambridge Center | ||
Cambridge, MA 02142 | ||
USA |