From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 109fba,4873305131bf4d94 X-Google-Attributes: gid109fba,public X-Google-Thread: 1014db,4873305131bf4d94 X-Google-Attributes: gid1014db,public X-Google-Thread: 103376,4873305131bf4d94 X-Google-Attributes: gid103376,public From: "Samuel T. Harris" Subject: Re: Porting Experiences (was Ada and Pascal etc ) Date: 1997/11/07 Message-ID: <3463A34A.7FEED707@hso.link.com> X-Deja-AN: 287771967 References: <34557f2b.1934172@news.mindspring.com> <345E3ACD.A15@gsg.eds.com> <63mcmm$r3s$1@helios.crest.nt.com> <3460A7BB.3CCD27DC@hso.link.com> <63qq9k$njt$1@helios.crest.nt.com> Organization: Hughes Training Inc. - Houston Operations Newsgroups: comp.lang.ada,comp.lang.c,comp.lang.c++ Date: 1997-11-07T00:00:00+00:00 List-Id: Before I begin a point-to-point response, I must say it is refreshing to read a response devoid of ego. I applaud you and others who are glad to entertain considered discussions filled with details and facts on the comparative merits. I also salute your willingness to provide complete C code supporting your position. Kaz Kylheku wrote: > > In article <3460A7BB.3CCD27DC@hso.link.com>, > Samuel T. Harris wrote: > >Reading the arguments between Kaz and others, I'm struck > >with the realization that Kaz is missing a significant > >point. As long as application code is not concerned > >with the representation of variables, Kaz is correct > >in his statements that a few simple guidelines insure > >good type choices for portable C code. What Kaz has > >failed to consider, but has been state by others, is > >that sometimes the representation of the type IS > >important to the application, or at least to the > >context in which the application is running. > > Then the application is not portable, by definition. A portable program is one > which is not concerned with the representation of a type. I don't agree. Portability is the ability to compile an run the same source in several environments. Type representation is not a application attribute which determines portability. IMHO a portable program is one which has to run or has potential to run on heterogenous platforms. By platform I mean the combination of hardware, operating system, and compiler. Restrictions on type selection are usually imposed on the context and many times that context requires the program to satisfy those restrictions in a portable way because the context spans many platforms. In such contexts, applications do need to be concerned with the representation of type AND still be portable. In such domains, language choice for the project must recognize the merits of candidate languages and their facilties which support satisfying these needs. I recognize that the need for distributed computing involving heterogenous platforms is on the rise. This means that application domains which did not care about type representation are now having to consider such issues given the need/want to run such almost anywhere. > > >The classic example here is a 32-bit integer. While > >application usually are only concerned witht he RANGE > >supported by the type (and Kaz's guidelines do insure > >a proper choice of type) the context in which the > > Those are not only my guidelines, but have been reiterated by other comp.lang.c > regulars. They are also reflected in the comp.lang.c FAQ. As you say. A good thing recognized by the C establishment as a good thing. > > >app is running may force the use of a 32-bit integer, > >especially when interfacing to hardware, COTS libraries, > > Interfacing to hardware is outside of the domain of a strictly conforming > C program. A pure C language program communicates with the environment > only through streams. > This handicaps C for use in embedded systems. > There are ways, using C, to conform to external storage layouts in maximally > portable ways which do not depend on the representation of types other > than the type unsigned char. Which, as you detail below, involve conversion routines since the native C types cannot be used on the storage layouts. While this is a solution, it does have an execution cost (calling the conversion routines). This is not to say that Ada is maximally efficient when using representation clauses. There are times when a specified record layout causes the compiler to emit inefficient code simply because the required layout is not "natural" to the platform. Such situations usually are the result of doing simulation work on hardware other than the intended target. More on that later. > > >or in a distributed environment where heterogenous > >architectures must interface with each other. These > > I have programmed in such circumstances and managed to remain strictly > conforming. Interfacing heterogeneous architectures can be solved by > identifying a canonical external representation format and then writing > maximally portable routines which encode data items to and from that > format. In my experience, only floating point representations represent > any significant difficulties in this area. That summarizes my experiences as well. Its just that with Ada, I can dispense with the conversion/encoding routines when the format lends itself to direct manipulation. I can't do that with C. > > >are common examples of the context forcing a representation. > >C does not support forcing the representation in a > >portable way. Ada does. The need for such cannot > >be simply dismissed because the need is real. > > But C allows you to manipulate individual bytes, and therein lies the > secret. I can manipulate individual bytes with Ada, but I don't have to in order to achieve portable code in a context requiring specific type representations, so I don't. > > >In fact, Ada provides me facilities to exactly map > >the representation of a record right down to the > >location and size of each field to conform to the > >requirements of memory-mapped hardware registers. > > This is also possible with C in a portable way. It is not that convenient, of > course, but we are discussing portability, rather than convenience. > > >This is very powerful and convenient. I can even > > I couldn't agree more, but please stick to the topic which is portability. This whole thread is about compiling and running the same source on heterogenous environments. This is on topic and has been all along. > > >So, I can't say to Kaz that he is wrong, because > >he is not, as far as he goes. What I do say to Kaz > >is "You have only pricked the tip of the portability > >iceberg." Portability involves much more than guaranteeing > > That's because I was only asked to scratch the surface, because > the subject that arose was the choice of integral types to suit > particular requirements. Now we are on the topic of conforming > to external storage formats, which is something else. You haven't > requested a discussion of this topic before. We'll, this was brought up in prior messages leading up to this thread. Perhaps you missed that aspect but we are both on the same track now. No matter, I see you have a complete grasp on the situation now discussed. > > Conforming to external data layout can be done in a highly portable way in C. > It can also be done in non-portable ways which are usually faster. > > Instead of useless talk, why don't we try the following game: you describe the > storage layout, and I will demonstrate a maximally portable C example which can > communicate with that layout. I will entertain you as long as you wish. > > Perhaps you will emerge out of this better armed for situations in which > you have to use C rather than some other preferred tool such as Ada. Been there, done that in C. Been there, still doing that in Ada, and with much less hassle. Subsequent messages on this thread have gone through this exercise so I'll refer to them instead of duplicating the effort (or asking your to duplicate). Your solution, both described in abstract above and in implementation detail in other messages involves conversions between an artificial intermediate representation which bears no resemblence to the required types into and out of a C structure which only resembles the required items but do not conform to the specifications of the type. With these three components (the intermediary type, the abstract type, and the conversion routines) you do solve the problem is communications were involved. I note the amount of code required to support this architecture (conversion routines). I also note the three separate maintenance areas involved. The target type specifies range, size, and layout. Size is maintained in the intermediary type. Range is maintained in the abstract type (at least as well as C can support it). And layout is maintained in the conversion routines. The same situation in Ada dispenses with the conversion routines (and the associated execution cost AND life-cycle maintenance) by building the structures to the exacting specifications of the context. Hence the code remains portable and simple. I submit that your solution, while it can work, is not simple. My maintenance is localized to a groups of type declarations and representation clauses, all of which read very naturally compared to the type specification itself. To reimplement your solution in Ada, I simply declare a base type sans representation clauses and declare derived types from the base type and apply the necessary representation clauses for the various type specifications I required. This allows the compiler to use a most efficient layout for the base (which I can manipulate as the abstract type). I can then use simple Ada type conversions (without writting a single line of supporting code) to convert from one layout to another. In fact, my current project has a group which passes hardware data around. We have the actual hardware to deal with, and a hardware simulator produced by a third part to deal with. Unfortunately, then don't used exactly the same layout (how the third party got away with that snafu is beyond me). We employ the method I have describe and presto, no hassel and no worries. I also submit that your solution does not support singleton access to the fields. Your solution works when the goal is communications. I get a packet, access and manipulate, and possible resent the packet. Your solution does not work when the structure must reside on top of a memory-mapped hardware location. In general, I CANNOT decode the whole packet at once NOR can I decode the entire packet when I'm done. Some hardware interfaces are sensitive to not only what I place in memory, but if I place anything in memory. Bit splillage and extra access are not allowed. Again, the Ada allows me to not only layout the type as required, but also overlay the variable where it needs to be. Because the type naturally maps to the desired representation, I can read/write only the fields I need as the situation required. I invite you to extend your solution to support singleton read/write access to each field of the structure. I know it can be done, but how much more code do you have to write, how many more points of maintenance are introduced, how much more execution penaly do is incured, how much more risk of failure is involved. > > >products with custom code. C simply does not have the > >language features to support any but the most > >rudimentary porting requirements of single-machine, > >black-box applications that run by themselves or > >with others in a strictly homogeneous environment > >all of which are built with a strictly compatible > >set of tools. > > That depends on what you mean by language features. If you mean that C > doesn't have language features that are *specifically* designed to help you in > this area, then you are right. Which has been my point all along. Portability has little to do with the needs of the application and everything to do with the needs of the context. The context demands the code run in several environment. This means portability of source code. It is becoming increasing common for the context to also demand that code support a particular type representation. At the risk of repeating myself, portable code which cannot support specific type representations is only portable in single-machine, black-box applications that run by themselves _or_ with others in a strictly homogenous (type consistent) environment all of which are built with a strictly compatible (type consistent) set of tools. I submit that those days are rapidly ending. Even in the world of embedded and dedicated system, which are traditionally written for a single target architecture, those days are ending. More and more development of such system are preceeded or are in parallel to efforts to simulate the system either for training or verification. Reuse of code across all three areas is desirable to cut costs. Usually, the training environment is vastly different from the target environment and for verification, both environment must talk to each other. Hence, the "real" code must conform to the target's representation of things and the "fake" code (for training/simulation) must also conform especially when used with "real" hardware for verification. Such situations are becoming more the norm than the exception so any discussion of portability, which enables reuse, must consider portable specification of contextually determined type representations. Finally, on the "real" target, I can ill-aford the extra time and risk of using conversion routines due to the real-world time response/latency requirements. Given the frequency such conversion take place, the "fake" target also can ill-aford conversion routines because the simulator is doing so many other things to support training and verification that I quickly run out of CPU horsepower no matter how big my computers. Bigger computers just mean bigger simulations, not more resources for supporting activities. -- Samuel T. Harris, Senior Engineer Hughes Training, Inc. - Houston Operations 2224 Bay Area Blvd. Houston, TX 77058-2099 "If you can make it, We can fake it!"