Ubuntu: not GNU anymore. An opportunity for Ada/SPARK?

Yep, take for example this gem:

ODMActivate
ODMSTATUS ODMActivate (ODMHANDLE handle, WORD action,
LPSTR lpszDocId)
This function causes the DMS to perform actions that do not require cooperation
from the calling application. Control is returned to the calling application after
the specified action has been completed, except where noted. A DMS is not
required to support all of these actions.

Parameters:
handle- in - A handle obtained by a previous ODMRegisterApp call.
action- in - One of the following action codes:

  • ODM_NONE- No specific action is requested. The DMS should
    simply make itself visible and let the user select the action to
    be performed.
  • ODM_DELETE- The DMS should delete the specified document.
    Note that most DMSs will not allow a deletion to occur if the
    document is currently in use.
  • ODM_SHOWATTRIBUTES- The DMS should display the
    specified document’s profile or attributes.
  • ODM_EDITATTRIBUTES- The DMS should display the specified
    document’s profile or attributes, and the user should be put
    in edit mode. Note that some DMSs will not allow a
    document’s attributes to be edited while it is in use.
  • ODM_VIEWDOC- The DMS should display the specified
    document in a viewer window. The DMS may return control
    to the calling application before displaying the document.
  • ODM_OPENDOC- The DMS should open the specified document
    in its native application. The DMS may return control to the
    calling application before displaying the document. This
    function is intended for use by applications other than the
    document’s native application (e-mail, workflow, annotation,
    etc.). Applications should use ODMOpenDoc to access
    their own documents. If this function fails, the calling
    application may wish to retry using the ODM_VIEWDOC
    action code.
  • ODM_NEWDOC - The DMS should allow the user to create and
    save a new document. Optionally the caller can specify a
    template document in lpszDocId. If lpszDocId is Null the
    DMS should allow the user to choose the file format of the
    document to be created and the document template. In
    most cases it is expected that the DMS will need to launch
    an application to create the document. The DMS may return
    before satisfying this call, in which case the calling
    application will not get notification when the new document
    has been created. The user is free to cancel this function.
  • ODM_CHECKOUT - The DMS should check-out/reserve the
    document for the current user. The DMS can display
    whatever UI it might use for document check-out. This
    action allows the user to explicitly reserve a document in the
    DMS in a way that is persistent across ODMA or DMS
    sessions. ODMOpenDoc should be used to get the content
    file. See ODMCloseDoc and ODMCloseDocEx for
    recommendations on how to handle closing a document that
    was explicitly reserved before it was opened.
  • ODM_CANCELCHECKOUT - The DMS should cancel a previous
    checkout/reserve on the document, if it has been checked
    out by the current user. The DMS can display whatever UI it
    might use for canceling a document check-out.
  • ODM_CHECKIN - The DMS should check-in/unreserve the
    document if it’s checked-out by the current user. The DMS
    can display whatever UI it might use for document check-in.
    ODMSaveDoc or ODMSaveDocEx should already have
    been used, if necessary, to save the content to the DMS.
    ODM_SHOWHISTORY - The DMS should display the specified
    document’s history (i.e. revisions, events, activities, etc.).
    lpszDocId - in - A document ID specifying the document on which to
    perform the requested action. This parameter may be Null if the action is
    ODM_NONE or ODM_NEWDOC. If action is ODM_NEWDOC the
    application can specify the document ID of a template document.
    Return value:
  • ODM_SUCCESS if successful.
  • ODM_E_DOCID if the document ID is invalid or refers to a document
    that no longer exists.
  • ODM_E_INUSEif the document is currently in use or checked-out by
    another user on actions where this would preclude the
    operation from completing correctly.
  • ODM_E_ACCESS if the user doesn’ t have appropriate access rights
    to perform the requested action (i.e. check-out or check-in the
    document).
  • ODM_E_OFFLINE if the DMS cannot currently access the document
    because the user client is off-line.
  • ODM_E_ARCHIVED if the DMS cannot currently supply the document
    content because it has been archived.
  • ODM_E_CANCEL if the action was canceled by the user.
  • ODM_E_NOSUPPORT if action is not supported by the DMS.
  • ODM_E_ITEM if action is invalid or not supported by the DMS.
  • ODM_E_FAIL if the action could not be completed by the DMS.
  • ODM_W_NOACTION if action is ODM_CHECKOUT and the
    document is already checked-out/reserved by the current user.
    This status can also be returned if action is either
    ODM_CANCELCHECKOUT or ODM_CHECKIN and the
    document is not currently checked-out/reserved by any user.
  • ODM_E_HANDLE if handle was invalid.

And so, to properly present this out, after enumerating the type, you need to do

Function ODMActivate(
  the_odmHandle : ODMHANDLE;        -- autogen type, remember to isolate these from leaking
  action        : minwindef_h.WORD, -- autogen type, remember to make sure sizes are correct
  lpszDocId     : winnt_h.LPSTR     -- autogen type, remember to make sane translation
 ) return ODMSTATUS
   with Export, Convention => C, External_Name => "ODMActivate",
   Pre  =>  Interfacing.Action'(+action) in NONE | DELETE | SHOWATTRIBUTES | 
            EDITATTRIBUTES | VIEWDOC | OPENDOC |  CHECKOUT | CANCELCHECKOUT |
            CHECKIN,
   Post => +ODMActivate'Result in SUCCESS | DOCID | OFFLINE | TRUNCATED |
            Interfacing.ITEM | NOSUPPORT | HANDLE;

And that’s just one function-call, and this isn’t factoring out the various inputs/outputs into types and subtypes… you want a good tool, make one that can read API-specs like this and generate the appropriate types and subtypes, the appropriate subprogram headers… make one that can ingest OpenGL and spit out a reasonable, correct, complete thick Ada binding.

But the C way is “document” “everything” and force the consistency-checking onto the user/implementer… because “simple”.

No, the drivers are what interfaces into the hardware. It matters not what they are written in so long as they (a) correctly access/operate the hardware, and (b) correctly interface into the host OS — but you’ve illustrated exactly how C cripples software engineering: you confused the OS’s implementation-language with what is usable, and what is usable with what is suitable, and both of those with what is most convenient right-here/right-now, labeling it as “natural”.
Do you see it?

(Besides, this gets to a decades-long sore spot of mine: C is not the best/only[-real] OS-dev language. In the Burroghs it’s Algol, in most pre-Windows OSes it’s assembly for that particular architecture, for the original Mac it was Pascal, for VMS it was literally “what makes the most sense” thanks to their common-language environment.)

I have very mixed feelings about that.

:money_mouth_face: :money_bag: :crab:

bindgen

but wait, there’s moar!
autocxx
cxx

Having said that:

  • Rustaceans tend to give these things higher reviews than they deserve. I’ve had to use them. They are indeed engineering marvels. But they still have issues. I’ve even reported some, and I think I contributed a fix to one.
  • In my experience, GNAT’s generator for thin bindings is pretty usable on C source. But my experience is limited to using it on glpk.
  • So it’s possible that Rust’s transpilers/binding generators, while good, are not in fact any better than what’s available for Ada, so long as you’re using GNAT.

Lilith, Medos, Oberon.

Er, no thanks.

I have the start of a good tool, but it’s very difficult to generate thick bindings and to autogenerate subtypes when there’s no information, I’m not that far into it and distracted with something else rn.

Pretty sure Windows <= 3.1 was written in Pascal.

Exactly.

Rustaceans are the new Stakhanovists.

Sometimes they do great things! Our entire graphical remote maintenance infrastructure is based on Rustdesk, a truly free tool, with our own encryption keys, and a proxy relay on one of our instances to handle all our channels. A really brilliant piece of software :slight_smile:

1 Like

By successful I mean quite well known and well used. Let’s take Lilith (I didnt know about), it only has a FAT16 file system support according to its web page… I won’t take it as a production OS despite of the quality of the language. But I guess it can be nice to experiment with it. (But the Mirage OS with its unikernel approach can fill a niche)

It WAS a production OS when it was created in the 70’s/80’s and FAT was enough back then for that. But in the 80’s, we on Amiga had a few filesystems including FAT.

I can’t speak to prior 3.1, but 3.1 was primarily in C if that helps. I believe there were some pascal written libraries though, if I remember correctly.

Dave Cutler, seeing the Windows 3.1 C and asm sources he had to recover for the Windows 3 subsystem of Windows NT 3, refused to use them and had everything recoded in “clean C++”. I haven’t found a recent source to confirm this, but I remember the anecdote well. By the way, Windows NT 3 (kernel, fs, etc.) is coded in plain C.

Note that I have quoted several points against the inclusion of Rust drivers into Linux (they are not from me). Some points are more relevant than others, but we can see how an « alien » language in an OS can be welcomed…

An other reason is perhaps that Ada is not known as it deserves. In my Graduate Engineering School, I wasn’t been exposed enough to the Ada language… I was mainly exposed to C, to Caml, (Z method) but not much languages. (Ok, I had a look on Modula-3 but not as my main curse) It was before GNAT when compilers cost a lot… then I guess Ada missed an occasion to be known and appreciated. Ok, GNAT was available in 1995… (a little late), but afterwards, we need libraries. Easy to get in C (just « apt install www-dev » in Debian, « dnf … » in RedHat and so on), easy on python (pip install …), Rust learned the lesson (cargo)… Ok with Ada we have Alire, but in 2021… much much time lost (Remember, a developper doesn’t choose a language, but an ecosystem).

Surely, I won’t develop a driver with Alire libraries, but Alire libraries could have been useful to help the job done of some developper for other project, and when the developers is accustomed with Ada, he is ready to use it for drivers.

I remember reading years ago that win was pascal like macos was.

NT was a different beast, it was written as a microkernel by DEC engineers they poached.

I’m not sure this is comparable to the amount of work being done in embedded and in any case perception matters. Ada’s standard library and its wider ecosystem don’t exactly scream “general-purpose”. Do you think that C++ or Rust communities have similar ratios of low-level to high-level programmers in comparison to Ada? I’d wager Ada’s community is much more on the embedded side, working in specialized domains, close to hardware.

1 Like