.. Copyright (C) 2024-2025 Free Software Foundation, Inc.
   Originally contributed by David Malcolm <dmalcolm@redhat.com>

   This is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see
   <https://www.gnu.org/licenses/>.

.. default-domain:: c

Tutorial part 1: "Hello world"
==============================

Before we look at the details of the API, let's look at building and
running programs that use the library.

Here's a toy program that uses libgdiagnostics to emit an error message
to stderr.

  .. literalinclude:: ../../../testsuite/libgdiagnostics.dg/test-example-1.c
     :language: c
     :start-after: /* begin quoted source */
     :end-before:  /* end quoted source */

Copy the above to `tut01-hello-world.c`.

Assuming you have libgdiagnostics installed, build the test program
using:

.. code-block:: console

  $ gcc \
      tut01-hello-world.c \
      -o tut01-hello-world \
      -lgdiagnostics

You should then be able to run the built program:

.. code-block:: console

  $ ./tut01-hello-world
  progname: error: I'm sorry Dave, I'm afraid I can't do that

If stderr is connected to a terminal, you should get colorized output
(using `SGR control codes <https://en.wikipedia.org/wiki/ANSI_escape_code>`_).

.. image:: example-1.png

Otherwise, the output will be plain text.

Obviously a trivial example like the above could be done using ``fprintf``
on stderr, and it's fairly easy to colorize text at the terminal.

In :doc:`the next part of the tutorial <02-physical-locations>` we'll add
file/location information to our error messages, and libgdiagnostics will
quote the pertinent parts of the file, underlining them, which is less trivial
to reimplement.  libgdiagnostics gives us many other such abilities, such as
fix-it hints and execution paths, which we'll cover in the following
tutorials.  Also, once a program's diagnostics are using libgdiagnostics,
it is trivial to add support for outputting them in
machine-readable form as :doc:`SARIF <../topics/sarif>`.


Structure
*********

The above example shows the typical structure of a program using
libgdiagnostics:

* **initialization**: create a :type:`diagnostic_manager` instance,
  and create an output sink for it, and other one-time initialization

* **emission**: create various :type:`diagnostic` instances, populating
  them with data, and calling "finish" once they're ready to be emitted.
  :doc:`Text sinks <../topics/text-output>` emit their diagnostics as soon
  as "finish" is called on them.

* **cleanup**: call :func:`diagnostic_manager_release` on the
  :type:`diagnostic_manager` to finish and free up resources.
  :doc:`SARIF sinks <../topics/sarif>` write their output when
  :func:`diagnostic_manager_release` is called on the manager.

For non-trivial examples we'll also want to create location information,
which could happen during initialization, or during a parsing phase of
the program using libgdiagnostics.  See :doc:`02-physical-locations` for
more information.


Formatted messages
******************

The above example uses :func:`diagnostic_finish`, which takes a format
string and arguments.  libgdiagnostics has its own style of format
string arguments used for :func:`diagnostic_finish` and some other
entrypoints.

.. note:: The format syntax is *not* the same as ``printf``; see
   :doc:`supported formatting options <../topics/message-formatting>`.

You can use the ``q`` modifier on arguments
to quote them, so, for example ``%qs`` is a quoted string, consuming a
``const char *`` argument::

   diagnostic_finish (d, "can't find %qs", "foo");

This gives output like this:

.. code-block:: console

  progname: error: can't find ‘foo’

where the quoted string will appear in bold in a suitably-capable
terminal, and the quotes will be internationalized, so that e.g. with
``LANG=fr_FR.UTF8`` we might get:

.. code-block:: console

  progname: erreur: can't find « foo »

Note that:

* the string ``error`` has been localized by libgdiagnostics to
  ``erreur``,

* locale-specific quoting has been used (``«`` and ``»`` rather than
  ``‘`` and ``’``),

* ``foo`` hasn't been localized - you would typically use quoted strings
  for referring to identifiers in the input language (such as function names
  in code, property names in JSON, etc),

* the message itself hasn't been localized: you are responsible for
  passing a translated format string to :func:`diagnostic_finish` if you
  want to internationalize the output.

There are many :doc:`supported formatting options <../topics/message-formatting>`.


Naming the program
******************

In the above output the message was preceded with ``progname``.  This
appears for diagnostics that don't have any location information associated
with them.  We'll look at setting up location information in the
:doc:`next tutorial <02-physical-locations>`, but we can override this
default name via :func:`diagnostic_manager_set_tool_name`::

   diagnostic_manager_set_tool_name (diag_mgr, "my-awesome-checker");

leading to output like this::

   my-awesome-checker: error: can't find ‘foo’

There are various other functions for
:doc:`supplying metadata to libgdiagnostics <../../topics/metadata>`.


Moving beyond trivial examples
******************************

Obviously it's not very useful if we can't refer to specific files and
specific locations in those files in our diagnostics, so read
:doc:`part 2 of the tutorial <02-physical-locations>` for information on
how to do this.
