Here is an example of why these things bother me.
Pascal:
If (x = True) Then
WriteLn('Error #',e,' in line #',l,' detected.');
Modula-2:
IF (x = TRUE) THEN
WriteString("Error #");
WriteCard(e);
WriteString(" in line #");
WriteCard(l);
WriteString(" detected.");
END;
M2 is too verbose.
Now, Modula 2 could be fixed, and should be fixed. Not having a variable
number of parameters makes compiler writing simpler, but makes writing
programs harder, and more time consuming. It may make debugging easier
though. Now, modula-2 and pascal are both missing bit-wise manipulators.
What is needed:
BAND bitwise and
BOR bitwise or
BXOR bitwise xor
BSHL function to shift bits left (returns the shifted number)
BSHR function to shift bits right
That helps alot. I had to write a microproccessor simulator in modula-2,
and the lack of bitwise operators made my life a living hell (along with
the problem of not having a variable number of parameters.)
Fix these design flaws and allow single statements to be written easier
and the language may even be usable. Hell, I may even use it!
Borland could fix modula-2 like they fixed pascal.
Modula-2 should never be forced upon students, it's inhumane.
--
/* Walter Reed UUCP : uunet!ndsuvax!ncreed
Internet : ncreed%NDSUVAX...@CUNYVM.CUNY.EDU
Ph 701-235-0774 Bitnet : ncreed@ndsuvax OR NU105451@NDSUVM1
------------------- */
In article <7...@ndsuvax.UUCP> ncr...@ndsuvax.UUCP (Walter Reed) writes:
>There are two major beefs I have with modula-2.
>1. Modula does not allow a variable number of parameters in function calls.
>2. Bitwise operators are not available (at least not standard.)
>Minor beef:
> Begin end's required even when only one statment used.
Addressing 1: Register oriented AOT stack oriented as in C
(although I heard that Lattice now has register optimization). This
is much faster runtime, although more verbose for the user.
Benchmark has C routines such as printf, etc., but you must first
initialize the parameter array before calling printf (still pretty
nice though).
2. Modula-2 has *ALWAYS* had bitwise operators. They are:
+ : inclusive OR
* : AND
/ : exclusive OR
These operators have special meaning only when applied to BITSET
types. For example:
CONST
mask = BITSET(15);
VAR
rotation : CARDINAL;
BEGIN
rotation := 0;
...
rotation := CARDINAL(BITSET(rotation+1)*mask);
...
Here we can increment a value from 0 to 15 and back again without
any bounds checking. In C we could do:
rotation = (rotation + 1) & 0xf; or maybe
rotation = ++rotation & 0xf; or maybe
++rotation &= 0xf;
Much less typing, but the same result.
The *only* time BEGINs are used in Modula-2 are for the start of
program code for PROCEDUREs or main MODULES. Everything terminates
with an END. This is an improvement over Pascal and C, as it stops
possible errors before they can start.
>Here is an example of why these things bother me.
>
>Pascal:
> If (x = True) Then
> WriteLn('Error #',e,' in line #',l,' detected.');
Why not:
IF x THEN printf(); END;
>M2 is too verbose.
Yeah, well, everything you want is available in C. Now, if you
want the MODULE construct, etc. native to M2, the 10000-30000 lines
per minute compilation times, "instant" linking, then take another
look at M2.
> Shifting...
FROM SYSTEM IMPORT SHIFT (* example code *)
SHIFT(x,1) x is unsgned, logical SL
SHIFT(x,1) x is sgned, artihmetic SL
SHIFT(x,-1) ... SR
It's all there. Remember M2 was created for the development of
large, system level software (like operating systems).
Other than for personal taste, and/or development
speed/portability, you can do anything on the Amiga with any of the
popular compiled languages available today.
John
I really like modula2. It's probably my favorite language. But
this WriteCard, WriteString stuff makes me want to pop someone in the nose.
It's as if someone told Prof. Wirth "heh, pascal's io is pretty bad, but
I bet you could make it EVEN WORSE."
I hate C as much as the next guy, but it seems to me that printf is
the solution. Has anyone ever written some kind of front end for a
modula compiler to turn printf's into WriteSh*t's? It doesn't seem
like it would be too hard, although you probably couldn't do it with a
macro processor like m4...could you?
--
+
| Duke Robillard
| AT&T Bell Labs m10ux!r...@ihnp4.UUCP
| Murray Hill, NJ {any biggy}!ihnp4!m10ux!rgr
I like C++'s overloading of the << and >> operator's even better than
printf. It allows you to define custom print routines for each structure
(class) declared, and then to print (to stdout for example) you do:
cout << god_awful_structure_instance;
The advantage of this approach over using procedures in
modula2 or pascal is (besides previty) that you don't have to
remember the type of structure your variable is; the compiler figures it out.
It does make programming a lot simpler, but is definitely non-portable to
any other Modula compiler I know of. Perhaps other modula enthusiasts
would like to post notes describing their favorite compiler's extensions,
or discuss how portable a given extension may be.
Another, more general solution, is the one we took when developing National's
Modula-2 compiler. We wanted to be able to interface with any C routine, even
those that weren't as strict as Modua-2 routines (e.g. num. & type of parameters
procedure or function, etc.). The following is an excerpt from the manual on the
extension we added for this purpose:
PSEUDO-MODULE 'C'
-----------------
A pseudo-module 'C' has been implemented which, like the pseudo-module SYSTEM
does not actually exist but is built into the compiler. Module C is used to
import C routines that cannot be defined using a Modula-2 definition, e.g.
routines that have a variable number of parameters (see following example).
Objects imported from module C have the following properties:
- The object must be a procedure.
- No type-checking is done on parameters to such procedures.
- The procedures can receive any number of pararmeters.
- The procedures can be called using either a procedure call or a function
call.
- Values returned by such procedures are of type WORD.
Example:
Give the IMPORT statement:
FROM C IMPORT printf;
all of the following statements are legal:
printf;
printf(string, integer, longreal);
cardinal = printf(string, integer, longreal);
Come on... give me a break. If you don't like the I/O subsystem, why don't
you re-write it??? A front-end translator in m4 is silly.
Besides, the whole idea of the WriteCard()-style I/O system is to remove the
20K overhead that printf() adds to programs. 95% of the functionality of
printf() is never used, and you're just making your text segment larger.
I've worked on a replacement for printf() in Modula-2 which allowed most of
the basic formatting of numbers/strings which are used regularly. It also
allowed for OOP Object I/O function definitions, which allow you to tell it
to Write an Object with the functionality of a c++ construct such as this:
cout << some_object_instance;
I'd post it, but it is based on a new I/O system (which I also worked on),
which is incompatible with Wirth's I/O system. (there used to be talk of
making the library we wrote Freeware, but I haven't seen it yet...)
--
Vincent Hatem
AT&T International, International Systems Operations, UNIX Technical Support
Telefon: (201) 953-8030
Please send all e-mail to: ihnp4!atti01!vch
Yeah, but that doesn't help me print out an error message, two strings,
and an integer return code. I don't want to have to write a method
for every print....
Overloading or procedure-name-abstraction is badly needed in Modula-2.
However, it needs to be applicable to ANY AND ALL procedures and
operators. For printing, I prefer:
Print(object, fieldWidth);
The programmer writes a Print procedure for each data type he defines
and/or wants to print.
Better yet, he writes a "BinToStr" procedure for each data type. Then Print
can be defined generically once:
PROCEDURE Print(object; fieldWidth: CARDINAL);
VAR
str: ARRAY [0..79] OF CHAR;
BEGIN
BinToStr(object, fieldWidth);
Display.WriteString(str);
END Print;
Notice that this also requires the additional capability to define
parameters of unspecified type. To compile this procedure, the
compiler generates abstract pseudo-code which is data-type independent
as its final output instead of object code. Object code for the procedure
is generated each time the compiler discovers an actual call to the procedure,
because only then can it know the data type of the typeless argument and
generate the correct code.
--
Alan Lovejoy; alan@pdn; 813-530-8241; Paradyne Corporation: Largo, Florida.
Disclaimer: Do not confuse my views with the official views of Paradyne
Corporation (regardless of how confusing those views may be).
Motto: Never put off to run-time what you can do at compile-time!
In C++:
#include <stream.h>
Then:
...
cout << "error message " << string1 << " " << string2 << " " << rc;
...
The header file defines printing for the ususal types.
Actually, the story I hear is that WriteCard was originally meant
(back when Wirth was developing languages on an old CDC machine)
to punch a card. Nostalgia being what it is, WriteCard now
prints unsigned integers.
If you'll believe that, you'll also probably believe that Modula-2
is an improvement on Pascal.
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi
>Besides, the whole idea of the WriteCard()-style I/O system is to remove the
>20K overhead that printf() adds to programs. 95% of the functionality of
>printf() is never used, and you're just making your text segment larger.
On 4.3 BSD on a Vax, I get the following:
% size doprnt.o
text data bss dec hex
2196 36 0 2232 8b8
% size printf.o
text data bss dec hex
40 36 0 76 4c
To use printf, it ups your text segment by a whole 2236 bytes. Wow.
It also isn't too slow: 4.3BSD doprnt is coded in assembly language
and manages to be quite fast. Puts is about 10% of that (200 bytes)
but isn't really any faster. But CERTAINLY NOT a "20K" overhead. Go
ahead and use printf. It doesn't really cost you that much.
N u m q u a m G l o r i a D e o
Michael I. Bushnell
HASA - "A" division
14308 Skyline Rd NE Computer Science Dept.
Albuquerque, NM 87123 OR Farris Engineering Ctr.
OR University of New Mexico
mi...@turing.unm.edu Albuquerque, NM 87131
{ucbvax,gatech}!unmvax!turing.unm.edu!mike
I doubt this is the reason -- hardly anybody cares about text segment size
any more, and in any case, printf is only 2K, not 20K. (In Ultrix -- your
mileage may vary.)
Wayne
WriteCard stands for WriteCardinal. There is a standard library module
CardinalIO that deals with the IO of cardinal numbers. In fact there is
a predefined data type CARDINAL. It has nothing to do with cards.
..Uday
A PASCAL-like write-procedure, with a variable number of parameters with
different types, can't be written as a normal procedure. But in a
similar way the compiler could change a statement like:
write( some_cardinal , some_string , some_whatever)
into calls to WriteCard, WriteString and WriteWhatever. (Some of these
procedures have extra parameters that must be specified in some way.)
This is in fact the way a PASCAL-compiler works, except the programmer
can't decide which WriteWhatever-procedures to be used.
A change like this seems to be close to the "spirit" of MODULA-2.
Any comments?
---------------------------------------------------------------------
Erik Jacobsen er...@daimi.dk
Computer Science Department Phone: +45 6 12 71 88 ext. 5226
Aarhus University
DK-8000 Aarhus, Denmark
---------------------------------------------------------------------
Neither would I. Fortunately for us, the i/o operators can be chained.
cout << "Error: file " << fname << ", line " << lnum
<< error_msg << "\n";
I think this is a big improvement over calls to overloaded "Print" procedures.
Details: "<<" associates left-to-right. `cout << "Error: file "' returns
cout as it's value, which is used as the left operand by `<< fname'. When
streams like cout (or the standard input, "cin") are used in an integer
context, the stream-to-int conversion returns the stream's status, so you
can write input loops like
while ( cin >> val ) { ...
If a programmer-defined type must be read or written, the programmer writes
"<<" and ">>" operators for it.
This isn't quite the whole picture; printf() is part of the
buffered I/O system, and so quite a bit of junk has to come
in with it. What follows shows what comes in on an HP-9000/850
(and perhaps proves that compiler people should be kept
on a short leash :->). Here's the poison:
-----------------------------------------------------
Script started on Thu Apr 14 09:28:14 1988
$ cat yow.c
main(){
printf("Hello, world\n");
}
$ cc -O -o yow yow.c
$ size yow
15844 + 3720 + 2604 = 22168
$ nm yow
Symbols from yow:
Name Value Scope Type Subspace
$global$ |1073741824|extern|data |$GLOBAL$
$START$ | 4523|extern|priprog|$CODE$
$dp$ |1073741824|extern|data |$GLOBAL$
$ARGV |1073745536|extern|data |$PFA_COUNTER$
$START_RTN$ | 4568|static|code |$CODE$
$UNWIND_START | 17144|extern|code |$UNWIND_START$
$UNWIND_END | 17896|extern|code |$UNWIND_END$
$RECOVER_START | 17896|extern|code |$RECOVER_START$
$RECOVER_END | 17896|extern|code |$RECOVER_END$
$PFA_C_START |1073745544|extern|data |$PFA_COUNTER$
$PFA_C_END |1073745544|extern|data |$PFA_COUNTER_END$
_mcount | 4575|extern|entry |$CODE$
$THISMODULE$ |1073741824|static|data |$DATA$
main | 4587|extern|entry |$CODE$
$THISMODULE$ |1073741840|static|data |$DATA$
printf | 4619|extern|entry |$CODE$
$THISMODULE$ |1073741840|static|data |$DATA$
environ |1073746576|extern|data |$BSS$
_start | 4739|extern|entry |$CODE$
$THISMODULE$ |1073741840|static|data |$DATA$
exit | 4779|extern|entry |$CODE$
$THISMODULE$ |1073741840|static|data |$DATA$
_iob |1073741848|extern|data |$DATA$ <- Buffering system
_smbuf |1073746584|extern|data |$BSS$
_bufendtab |1073742808|extern|data |$DATA$
_sibuf |1073747112|extern|data |$BSS$
_sobuf |1073745544|extern|data |$BSS$
_stdbuf |1073743052|extern|data |$DATA$
_lastbuf |1073741840|extern|data |$DATA$
$THISMODULE$ |1073743064|static|data |$DATA$
_lowdigit | 4819|static|entry |$CODE$
_dowrite | 4871|static|entry |$CODE$
_doprnt | 5043|extern|entry |$CODE$
$THISMODULE$ |1073743200|static|data |$DATA$
errno |1073748144|extern|data |$BSS$
_cleanup | 9819|extern|entry |$CODE$
fclose | 10087|extern|entry |$CODE$
_exitcu | 9895|extern|entry |$CODE$
fflush | 10263|extern|entry |$CODE$
_xflsbuf | 10903|extern|entry |$CODE$
_flsbuf | 10415|extern|entry |$CODE$
_wrtchk | 11127|extern|entry |$CODE$
_bufsync | 11707|extern|entry |$CODE$
_findbuf | 11339|extern|entry |$CODE$
$$divide_by_constant| 2051|extern|milli |$MILLICODE$ <- RISC divides
$$divI_2 | 2051|extern|milli |$MILLICODE$ are nasty!
$$divI_4 | 2067|extern|milli |$MILLICODE$
$$divI_8 | 2083|extern|milli |$MILLICODE$
$$divI_16 | 2099|extern|milli |$MILLICODE$
$$divI_3 | 2115|extern|milli |$MILLICODE$
$neg3 | 2136|static|code |$MILLICODE$
$pos | 2336|static|code |$MILLICODE$
$neg | 2420|static|code |$MILLICODE$
$$divU_3 | 2159|extern|milli |$MILLICODE$
$$divI_5 | 2183|extern|milli |$MILLICODE$
$neg5 | 2200|static|code |$MILLICODE$
$$divU_5 | 2227|extern|milli |$MILLICODE$
$$divI_6 | 2251|extern|milli |$MILLICODE$
$neg6 | 2272|static|code |$MILLICODE$
$$divU_6 | 2299|extern|milli |$MILLICODE$
$$divU_10 | 2323|extern|milli |$MILLICODE$
$pos_for_17 | 2352|static|code |$MILLICODE$
$$divI_10 | 2391|extern|milli |$MILLICODE$
$neg10 | 2408|static|code |$MILLICODE$
$neg_for_17 | 2436|static|code |$MILLICODE$
$$divI_12 | 2479|extern|milli |$MILLICODE$
$neg12 | 2496|static|code |$MILLICODE$
$$divU_12 | 2515|extern|milli |$MILLICODE$
$$divI_15 | 2535|extern|milli |$MILLICODE$
$neg15 | 2548|static|code |$MILLICODE$
$$divU_15 | 2559|extern|milli |$MILLICODE$
$$divI_17 | 2571|extern|milli |$MILLICODE$
$neg17 | 2596|static|code |$MILLICODE$
$$divU_17 | 2623|extern|milli |$MILLICODE$
$u17 | 2632|static|code |$MILLICODE$
$$divI_7 | 2651|extern|milli |$MILLICODE$
$neg7 | 2728|static|code |$MILLICODE$
$7 | 2652|static|code |$MILLICODE$
$pos7 | 2668|static|code |$MILLICODE$
$1 | 2708|static|code |$MILLICODE$
$2 | 2720|static|code |$MILLICODE$
$8 | 2732|static|code |$MILLICODE$
$neg7_shift | 2744|static|code |$MILLICODE$
$3 | 2784|static|code |$MILLICODE$
$4 | 2800|static|code |$MILLICODE$
$$divU_7 | 2811|extern|milli |$MILLICODE$
$$divI_9 | 2835|extern|milli |$MILLICODE$
$neg9 | 2860|static|code |$MILLICODE$
$$divU_9 | 2887|extern|milli |$MILLICODE$
$$divI_14 | 2915|extern|milli |$MILLICODE$
$neg14 | 2924|static|code |$MILLICODE$
$$divU_14 | 2919|extern|milli |$MILLICODE$
$$remI | 2939|extern|milli |$MILLICODE$
t1 | 2972|static|code |$MILLICODE$
finish | 3236|static|code |$MILLICODE$
$THISMODULE$ |1073743200|static|data |$DATA$
__ctype |1073743200|extern|data |$DATA$
_ctype |1073743216|extern|data |$DATA$
_ectype |1073743204|extern|data |$DATA$
_1kanji |1073743208|extern|data |$DATA$
_2kanji |1073743212|extern|data |$DATA$
$THISMODULE$ |1073744248|static|data |$DATA$
ecvt | 11763|extern|entry |$CODE$
cvt | 11839|static|entry |$CODE$
fcvt | 11803|extern|entry |$CODE$
mult32 | 14043|static|entry |$CODE$
$THISMODULE$ |1073745256|static|data |$DATA$
isatty | 14691|extern|entry |$CODE$
$THISMODULE$ |1073745256|static|data |$DATA$
malloc | 14739|extern|entry |$CODE$ <- Allocates for
free | 15439|extern|entry |$CODE$ buffered I/O
realloc | 15491|extern|entry |$CODE$
memcpy | 15699|extern|entry |$CODE$
byteloop | 15952|static|code |$CODE$
done | 15968|static|code |$CODE$
not_aligned | 15800|static|code |$CODE$
chekchunk | 15764|static|code |$CODE$
chunks | 15728|static|code |$CODE$
back_porch | 15780|static|code |$CODE$
subchunk | 15768|static|code |$CODE$
chkchnk2 | 15876|static|code |$CODE$
chunk2 | 15820|static|code |$CODE$
bp_0 | 15912|static|code |$CODE$
subchnk2 | 15880|static|code |$CODE$
bp_1 | 15916|static|code |$CODE$
encore | 15956|static|code |$CODE$
$THISMODULE$ |1073745288|static|data |$DATA$
_nl_name |1073745352|extern|data |$DATA$ <- For native language
_nl_langid |1073745288|extern|data |$DATA$
_nl_radix |1073745292|extern|data |$DATA$
_sh_low |1073745296|extern|data |$DATA$
_sh_high |1073745300|extern|data |$DATA$
_nl_char_size |1073745304|extern|data |$DATA$
_nl_direct |1073745308|extern|data |$DATA$
_nl_dgt_alt |1073745368|extern|data |$DATA$
_nl_dascii |1073745404|extern|data |$DATA$
_nl_punct_alt |1073745424|extern|data |$DATA$
_nl_pascii |1073745492|extern|data |$DATA$
_nl_space_alt |1073745312|extern|data |$DATA$
_nl_mode |1073745316|extern|data |$DATA$
_nl_order |1073745320|extern|data |$DATA$
_nl_outdigit |1073745324|extern|data |$DATA$
_nl_era |1073747072|extern|data |$BSS$
_seqtab |1073745328|extern|data |$DATA$
_pritab |1073745332|extern|data |$DATA$
_tab21 |1073745336|extern|data |$DATA$
_tab12 |1073745340|extern|data |$DATA$
_chrtab |1073745344|extern|data |$DATA$
strlen | 15979|extern|entry |$CODE$
$null_ptr | 16068|static|code |$CODE$
$not_aligned | 16000|static|code |$CODE$
$loop | 16020|static|code |$CODE$
$end_loop | 16036|static|code |$CODE$
$out | 16060|static|code |$CODE$
$THISMODULE$ |1073745528|static|data |$DATA$
fwrite | 16075|extern|entry |$CODE$
close | 16691|extern|entry |$CODE$
fstat | 16723|extern|entry |$CODE$
write | 16755|extern|entry |$CODE$
$THISMODULE$ |1073745528|static|data |$DATA$
_exit | 16787|extern|entry |$CODE$
$$divI | 3259|extern|milli |$MILLICODE$
$$divoI | 3255|extern|milli |$MILLICODE$
negative1 | 3688|static|code |$MILLICODE$
small_divisor | 3552|static|code |$MILLICODE$
normal | 3264|static|code |$MILLICODE$
$$divU | 3703|extern|milli |$MILLICODE$
special_divisor | 3976|static|code |$MILLICODE$
normal | 3712|static|code |$MILLICODE$
big_divisor | 4112|static|code |$MILLICODE$
zero_divisor | 3984|static|code |$MILLICODE$
$neg2 | 4124|static|code |$MILLICODE$
$loop | 4168|static|code |$MILLICODE$
$$mulI | 4147|extern|milli |$MILLICODE$
$check | 4164|static|code |$MILLICODE$
$return | 4324|static|code |$MILLICODE$
$shmcand | 4316|static|code |$MILLICODE$
$addtmp | 4312|static|code |$MILLICODE$
$two | 4196|static|code |$MILLICODE$
$endloop | 4308|static|code |$MILLICODE$
$fiftnx | 4304|static|code |$MILLICODE$
$$mulU | 4335|extern|milli |$MILLICODE$
$loop | 4352|static|code |$MILLICODE$
$return | 4508|static|code |$MILLICODE$
$shmcand | 4500|static|code |$MILLICODE$
$addtmp | 4496|static|code |$MILLICODE$
$two | 4380|static|code |$MILLICODE$
$endloop | 4492|static|code |$MILLICODE$
$fiftnx | 4488|static|code |$MILLICODE$
memchr | 16819|extern|entry |$CODE$
memchrexit | 16852|static|code |$CODE$
memchrloop | 16832|static|code |$CODE$
memchrequal | 16848|static|code |$CODE$
__exit | 16867|extern|entry |$CODE$
errnet |1073746580|extern|data |$BSS$
$cerror | 16907|extern|entry |$CODE$
return | 16928|static|code |$CODE$
ioctl | 16947|extern|entry |$CODE$
$THISMODULE$ |1073745528|static|data |$DATA$
end |1073748148|extern|data |$BSS$
_minbrk |1073745528|extern|data |$DATA$ <- malloc() uses
_curbrk |1073745532|extern|data |$DATA$
brk | 16979|extern|entry |$CODE$
$THISMODULE$ |1073745536|static|data |$DATA$
sbrk | 17067|extern|entry |$CODE$
_brk | 17115|extern|entry |$CODE$
$ exit
script done on Thu Apr 14 09:30:10 1988
>The NEW/DISPOSE-procedures in MODULA-2 are special in the sense that
>they can't be written as normal procedures. The compiler translates
>statements with NEW/DISPOSE into appropriate calls to ALLOCATE/DEALLOCATE.
>ALLOCATE/DEALLOCATE must be available procedures, usually imported
>from Storage.
But you can write your own ALLOCATE/DEALLOCATE.
>A PASCAL-like write-procedure, with a variable number of parameters with
>different types, can't be written as a normal procedure. But in a
>similar way the compiler could change a statement like:
> write( some_cardinal , some_string , some_whatever)
>into calls to WriteCard, WriteString and WriteWhatever. (Some of these
>procedures have extra parameters that must be specified in some way.)
>A change like this seems to be close to the "spirit" of MODULA-2.
>Any comments?
I agree. Most of the complaints I've seen about IO in Modula-2
can be rectified by writing your own IO module. At least M2 LETS
you write your own routines! I wrote something in the spirit of
Software Tools for my own IO package.
Hal Chambers
Now include the size of the floating point libraries. On Microsoft 5.0 C,
calling printf links the floating point emulator, which is about 30K of code.
Is this significant? I think so. I once hacked out 300K out of a suite of
programs by transforming printf's to puts'es and also by using an integer-only
printf. Sometimes, every byte counts. Not all the world is a vax, you know.
-Eric, Called Ultrahacker
]]] cout << god_awful_structure_instance;
]]Yeah, but that doesn't help me print out an error message, two strings,
]]and an integer return code. I don't want to have to write a method
]]for every print....
]
]Neither would I. Fortunately for us, the i/o operators can be chained.
] cout << "Error: file " << fname << ", line " << lnum
] << error_msg << "\n";
This is cool. The syntax is a little bulky (how un-C-like) but
overall it looks good.
]I think this is a big improvement over calls to overloaded "Print"
]procedures.
However, I don't really see that this is any different than
overloading a print procedure. all you're doing is overloading "<<"
(i.e. making it handle strings, integers, reals, whatever), right?
...
[ cout << foo << bar; // etc. ]
>
> However, I don't really see that this is any different than
> overloading a print procedure. all you're doing is overloading "<<"
> (i.e. making it handle strings, integers, reals, whatever), right?
>
That's right. It's just easier to type and to read than having a
jillion "print"'s.
For better or worse (*better* in my opinion), C++ classes don't tend
to "know how to print themselves". Instead you overload the << operator
to print new classes. Also remember that in C++, "int" is not a class!!
So the function can't be a member of class int. Translated into
Smalltalk, the class "int" does not recognize the message "<<".
"Print an int" _could_ be an external function, defined this way:
ostream& operator<< (ostream& o, int a) {return o << (long)a;}
There is an argument to be made that it SHOULD be declared this way,
to reduce the number of member functions of ostream. That is to say,
to reduce the number of types which ostream "knows about".
But the way things are actually implemented, the function is a member of
ostream, and has this declaration:
ostream& operator<<(int a) { return *this<<long(a); }
In article <2...@jupiter.olyis.UUCP> e...@pluto.uucp (Eric Brown) writes:
>Now include the size of the floating point libraries. On Microsoft 5.0 C,
>calling printf links the floating point emulator, which is about 30K of code.
[stuff deleted]
>Not all the world is a vax, you know.
Conversely, not all the world is an IBM PC with a Microsoft compiler.
It is not difficult[*] to arrange for the linker to pull in a simple
printf() if the rest of the program does not use floating point, and a
full-blown floating point printf if it does. Just because Microsoft's
implementation is poor (in terms of space, at any rate) is no reason to
castigate printf itself.
-----
[*]What, never? Well, hardly ever. The trick is to have the linker
examine the undefined externals for floating-point library references,
and if present, link with `bigprintf.obj'; otherwise it should use
`littleprintf.obj'. It is just a Small Matter of Programming.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris
Interesting.... Turbo C only links in the FP emulator if you actually use
floats in your program. If you don't, you get an integer-only printf linked
in (which prints an error message if you try to use %f/%g/etc). And the
emulation code is less than 19K (that's the size of the .LIB).
Just did a quick compile of the "Hello, world" program using printf and puts:
PRINTF EXE 5720
PUTS EXE 4080
(about 2.5K of the .EXE is the stdio library).
--
{harvard,ucbvax}!b.gp.cs.cmu.edu!ralf -=-=- DISCLAIMER? I claimed something?
ARPA: RA...@CS.CMU.EDU FIDO: Ralf Brown 1:129/31 BIT: RALF%CS.CMU.EDU@CMUCCVMA
TalkNet: (school) | "Tolerance means excusing the mistakes others make.
(412)268-3053 | Tact means not noticing them." --Arthur Schnitzler
Turbo C 1.0 seems to do this.
This brings up an interesting question. The C compiler on the
Onyx Z8000 (R.I.P.) would generate a symbol "_fltused" if any
floating point of any kind was used in that particular module.
When the linker went to resolve everything, it loaded in the
floating-point emulator if this symbol was found and didn't if it
wasn't. As far as I could tell, this symbol was nothing more
than a indicator to ld(1). Does anybody else do this? It seems
so much more reasonable than the ubiquitous "-f" flag.
--
Steve Friedl V-Systems, Inc. Resident access(2) basher
fri...@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl
Kent, the man from xanth.
In fact, if your C implementation has a limited address space and a bulky
floating-point library and does NOT do this, complain to the implementors.
It's not a novel or strange idea. The very first C implementation, on the
pdp11, used this trick. If Microslop can't be bothered, don't buy their
compiler.
--
"Noalias must go. This is | Henry Spencer @ U of Toronto Zoology
non-negotiable." --DMR | {ihnp4,decvax,uunet!mnetor}!utzoo!henry
Onyx borrowed this from the original pdp11 C implementation, in fact, which
used this technique to pick up a non-floating-point printf if floating
point was not in use. It didn't even require any special trickery in the
linker: generate an external reference to fltused when floating-point is
used; have two versions of the internal floating-point-formatting function,
one which implements the full show and also defines fltused and one which
does the integer subset and doesn't define fltused; and arrange for the
fltused version to be seen by the linker before printf and the non-fltused
version are seen.
> ... It seems so much more reasonable than the ubiquitous "-f" flag.
It's a reasonable substitute for -f only if you assume that the hardware
never has proper floating-point support, or if you don't care about hauling
the floating-point software along unnecessarily. The Onyx came under the
former heading, as I recall.
The Mark Williams C compiler for the Atari ST sort of supports this
idea. The printf library function does not ordinarily include
floating point routines. If you specify the -f flag to the compiler,
the larger version of printf (with floating i/o) will be linked
instead. Not quite as elegant was what Chris proposed, but really
quite functional.
--
/\ - "Against Stupidity, - {backbones}!
/\/\ . /\ - The Gods Themselves - utah-cs!uplherc!
/ \/ \/\/ \ - Contend in Vain." - sp7040!obie!
/ U i n T e c h \ - Schiller - wes
Sorry about cross-posting this here, I didn't realize it had been
cross-posted, and forgot to edit the newsgroups line. Please, don't
post flames or send hate-mail!