home *** CD-ROM | disk | FTP | other *** search
- First a note on the copyright. This is the same one used by the
- X Consortium (fortunately no one has started copyrighting copyrights),
- so if your lawyers don't mind that one, they shouldn't mind this one.
- Simply put, you can do what you want with this, although if you are
- so inclined we'd appreciate it if you sent us back any enhancements,
- bug fixes, or other related material, so we can make it available to
- everyone else. But if you don't want to, you don't have to. So be it.
-
- So. What's here? It's an implementation of the Message Catalog System,
- as described in the X/Open Portability Guide (XSI Supplementary Definitions,
- X/Open Company, Ltd, Prentice Hall, Englewood Cliffs, New Jersey 07632,
- ISBN: 0-13-685850-3). Included is a version of gencat, to generate
- message catalogs, as well as the routines catgets, catopen, and catclose.
- There is also the beginings of an X/Open compliant set of print routines,
- but we'll talk about those later.
-
- I haven't done a man page yet (sorry, but I've got a product to get out
- the door, the pretty stuff has to come later). However you can use the
- definitions in the X/Open docs and it should all work. I have, however,
- added a series of pretty significant enhancements, particularly to gencat.
-
- As follows:
-
- Use: gencat [-new] [-or] [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]...
-
- This version of gencat accepts a number of flags.
- -new Erase the msg catalog and start a new one.
- The default behavior is to update the catalog with the
- specified msgfile(s). This will instead cause the old
- one to be deleted and a whole new one started.
- -h <hfile> Output identifiers to the specified header files.
- This creates a header file with all of the appropriate
- #define's in it. Without this it would be up to you to
- ensure that you keep your code in sync with the catalog file.
- The header file is created from all of the previous msgfiles
- on the command line, so the order of the command line is
- important. This means that if you just put it at the end of
- the command line, all the defines will go in one file
- gencat foo.m bar.m zap.m -h all.h
- If you prefer to keep your dependencies down you can specify
- one after each message file, and each .h file will receive
- only the identifiers from the previous message file
- gencat foo.m -h foo.h bar.m -h bar.h zap.m -h zap.h
- As an added bonus, if you run the following sequence:
- gencat foo.m -h foo.h
- gencat foo.m -h foo.h
- the file foo.h will NOT be modified the second time. gencat
- checks to see if the contents have changed before modifying
- things. This means that you won't get spurious rebuilds of
- your source everytime you change a message. You can thus use
- a Makefile rule such as:
-
- MSGSRC=foo.m bar.m
- GENFLAGS=-or -lang C
- GENCAT=gencat
- NLSLIB=nlslib/OM/C
- $(NLSLIB): $(MSGSRC)
- @for i in $?; do cmd="$(GENCAT) $(GENFLAGS) $@ $$i -h `basename $$i .m`.H"; echo $$cmd; $$cmd; done
-
- foo.o: foo.h
-
- The for-loop isn't too pretty, but it works. For each .m
- file that has changed we run gencat on it. foo.o depends on
- the result of that gencat (foo.h) but foo.h won't actually
- be modified unless we changed the order (or added new members)
- to foo.m. (I hope this is clear, I'm in a bit of a rush.)
-
- -lang <l> This governs the form of the include file.
- Currently supported is C, C++ and ANSIC. The latter two are
- identical in output. This argument is position dependent,
- you can switch the language back and forth inbetween include
- files if you care to.
-
- -or This is a hack, but a real useful one.
- MessageIds are ints, and it's not likely that you are going
- to go too high there if you generate them sequentially.
- catgets takes a msgId and a setId, since you can have multiple
- sets in a catalog. What -or does is shift the setId up to
- the high end of a long, and put the msgId in the low half.
- Assuming you don't go over half a long (usually 2 bytes
- nowadays) in either your set or msg ids, this will work great.
- Along with this are generated several macros for extracting
- ids and putting them back together. You can then easily
- define a macro for catgets which uses this single number
- instead of the two. Note that the form of the generated
- constants is somewhat different here.
-
- Take the file aboutMsgs.m
-
- $ aboutMsgs.m
- $ OmegaMail User Agent About Box Messages
- $
-
- $set 4 #OmAbout
-
- $ About Box message and copyrights
- $ #Message
- # Welcome to OmegaMail(tm)
- $ #Copyright
- # Copyright (c) 1990 by Alphalpha Software, Inc.
- $ #CreatedBy
- # Created by:
- $ #About
- # About...
- # A
- #
- #
- $ #FaceBitmaps
- # /usr/lib/alphalpha/bitmaps/%s
-
- Here is the the output from: gencat foo aboutMsgs.m -h foo.h
-
- #define OmAboutSet 0x4
- #define OmAboutMessage 0x1
- #define OmAboutCopyright 0x2
- #define OmAboutCreatedBy 0x3
- #define OmAboutAbout 0x4
- #define OmAboutFaceBitmaps 0x8
-
- and now from: gencat -or foo aboutMsgs.m -h foo.h
-
- /* Use these Macros to compose and decompose setId's and msgId's */
- #ifndef MCMakeId
- # define MCMakeId(s,m) (unsigned long)(((unsigned short)s<<(sizeof(short)*8))\
- |(unsigned short)m)
- # define MCSetId(id) (unsigned int) (id >> (sizeof(short) * 8))
- # define MCMsgId(id) (unsigned int) ((id << (sizeof(short) * 8))\
- >> (sizeof(short) * 8))
- #endif
-
- #define OmAboutSet 0x4
- #define OmAboutMessage 0x40001
- #define OmAboutCopyright 0x40002
- #define OmAboutCreatedBy 0x40003
- #define OmAboutAbout 0x40004
- #define OmAboutFaceBitmaps 0x40008
-
-
- Okay, by now, if you've read the X/Open docs, you'll see I've made
- a bunch of other extensions to the format of the msg catalog as well.
- Note that you don't have to use any of these and, with one exception,
- they are all compatible with the standard format.
-
- $set 4 #OmAbout
- In the standard the third argument is a comment. Here if the
- comment begins with a # then it is used to generate the setId constant
- (with the word "Set" appended). This constant is also prepended onto
- all of the msgId constants for this set. Anything after the first
- token is treated as a comment.
-
- $ #Message
- As with set, I've modified the comment to indicate an identifier.
- There are cleaner ways to do this, but I was trying to retain a
- modicom of compatibility. The identifier after # will be retained
- and used as the identifier for the next message (unless overridden
- before we get there). If a message has no previous identifier then
- no identifier is generated in the include file (I use this quite a
- bit myself, the first identifier is a Menu item, the next three are
- accelerator, accelerator-text and mnemonic - I don't need identifiers
- for them, I just add 1, 2 and 3).
-
- # Welcome to OmegaMail(tm)
- Finally the one incompatible extension. If a line begins with #
- a msgId number is automatically generated for it by adding one to
- the previous msgId. This wouldn't have been useful in the standard,
- since it didn't generate include files, but it's wonderful for this
- version. It makes it easy to reorder the message file to put things
- where they belong and not have to worry about renumber anything (although
- of course you'll have to recompile).
-
- That's about all for that.
-
- Now, what about the print routines? These are embarassing. They are
- a first pass. They support only %[dxo] and %[s], although they support
- *all* of the modifiers on those arguments (I had no idea there were
- so many!). They also, most importantly, support the position arguments
- that allow you to reference arguments out of order. There's a terrible
- hack macro to handle varargs which I wrote because I wasn't sure if it
- was okay to pass the address of the stack to a subroutine. I've since
- seen supposedly portable code that in fact does this, so I guess it's
- okay. If that's the case the code could become a lot simpler. I welcome
- anyone who would like to fix it up. I just don't know when I'll get
- the chance; it works, it's just ugly.
-
-
- One last comment. You probably want to know how reliable it is. I've tested
- the print routines pretty well. I've used the msgcat routines intensely,
- but I haven't exercised all of the options in the message catalog file
- (like all of the \ characters) although I have implemented them all.
- I'm pretty confident that all the basic stuff works, beyond that it's
- possible that there are bugs. As for portability, I've run it under
- BSD4.3 (Apollo) and SYSV-hybrid (SCO). (And I never want to see the
- words "System V with BSD extensions" again in my life.) I don't believe
- that there are any heavy dependencies on Unix, although using another
- system would probably require #ifdef's.
-
- I apologize for the state of the documentation, the lack of comments,
- the lack of testing, and all of the other things. This project is
- subsidiary to my primary goal (Graphical Email for Unix) and I'm afraid
- I haven't been able to spend the time on it that I would have liked.
- However I'll happily answer any questions that you may have, and will
- be glad to serve as a distribution point for future revisions. So if
- you make any changes or add more X/Open functions, send me a copy and
- I'll redistribute them.
-
- Best of luck!
- Kee Hinckley
- September 12, 1990
-
- Bugs:
- There is currently one known bug. Updating an existing message
- catalog sometimes seems to not generate complete header files.
- If in doubt, delete the catalog and regenerate the whole thing.
- Kee - 02-12-92
- Note, I've just applied a patch from <Jan.Djarv@sa.erisoft.se>
- that may fix this problem.
- 03-12-92
-