xref: /openbmc/qemu/docs/devel/qapi-domain.rst (revision 4f50fa9391bb314e1578a6827f1678c87da3db4a)
1======================
2The Sphinx QAPI Domain
3======================
4
5An extension to the `rST syntax
6<https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_
7in Sphinx is provided by the QAPI Domain, located in
8``docs/sphinx/qapi_domain.py``. This extension is analogous to the
9`Python Domain
10<https://www.sphinx-doc.org/en/master/usage/domains/python.html>`_
11included with Sphinx, but provides special directives and roles
12for annotating and documenting QAPI definitions
13specifically.
14
15A `Domain
16<https://www.sphinx-doc.org/en/master/usage/domains/index.html>`_
17provides a set of special rST directives and cross-referencing roles to
18Sphinx for understanding rST markup written to document a specific
19language. By itself, this QAPI extension is only sufficient to parse rST
20markup written by hand; the `autodoc
21<https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html>`_
22functionality is provided elsewhere, in ``docs/sphinx/qapidoc.py``, by
23the "Transmogrifier".
24
25It is not expected that any developer nor documentation writer would
26never need to write *nor* read these special rST forms. However, in the
27event that something needs to be debugged, knowing the syntax of the
28domain is quite handy. This reference may also be useful as a guide for
29understanding the QAPI Domain extension code itself. Although most of
30these forms will not be needed for documentation writing purposes,
31understanding the cross-referencing syntax *will* be helpful when
32writing rST documentation elsewhere, or for enriching the body of
33QAPIDoc blocks themselves.
34
35
36Concepts
37========
38
39The QAPI Domain itself provides no mechanisms for reading the QAPI
40Schema or generating documentation from code that exists. It is merely
41the rST syntax used to describe things. For instance, the Sphinx Python
42domain adds syntax like ``:py:func:`` for describing Python functions in
43documentation, but it's the autodoc module that is responsible for
44reading Python code and generating such syntax. QAPI is analogous here:
45qapidoc.py is responsible for reading the QAPI Schema and generating rST
46syntax, and qapi_domain.py is responsible for translating that special
47syntax and providing APIs for Sphinx internals.
48
49In other words:
50
51qapi_domain.py adds syntax like ``.. qapi:command::`` to Sphinx, and
52qapidoc.py transforms the documentation in ``qapi/*.json`` into rST
53using directives defined by the domain.
54
55Or even shorter:
56
57``:py:`` is to ``:qapi:`` as *autodoc* is to *qapidoc*.
58
59
60Info Field Lists
61================
62
63`Field lists
64<https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#field-lists>`_
65are a standard syntax in reStructuredText. Sphinx `extends that syntax
66<https://www.sphinx-doc.org/en/master/usage/domains/python.html#info-field-lists>`_
67to give certain field list entries special meaning and parsing to, for
68example, add cross-references. The QAPI Domain takes advantage of this
69field list extension to document things like Arguments, Members, Values,
70and so on.
71
72The special parsing and handling of info field lists in Sphinx is provided by
73three main classes; Field, GroupedField, and TypedField. The behavior
74and formatting for each configured field list entry in the domain
75changes depending on which class is used.
76
77Field:
78  * Creates an ungrouped field: i.e., each entry will create its own
79    section and they will not be combined.
80  * May *optionally* support an argument.
81  * May apply cross-reference roles to *either* the argument *or* the
82    content body, both, or neither.
83
84This is used primarily for entries which are not expected to be
85repeated, i.e., items that may only show up at most once. The QAPI
86domain uses this class for "Errors" section.
87
88GroupedField:
89  * Creates a grouped field: i.e. multiple adjacent entries will be
90    merged into one section, and the content will form a bulleted list.
91  * *Must* take an argument.
92  * May optionally apply a cross-reference role to the argument, but not
93    the body.
94  * Can be configured to remove the bulleted list if there is only a
95    single entry.
96  * All items will be generated with the form: "argument -- body"
97
98This is used for entries which are expected to be repeated, but aren't
99expected to have two arguments, i.e. types without names, or names
100without types. The QAPI domain uses this class for features, returns,
101and enum values.
102
103TypedField:
104  * Creates a grouped, typed field. Multiple adjacent entries will be
105    merged into one section, and the content will form a bulleted list.
106  * *Must* take at least one argument, but supports up to two -
107    nominally, a name and a type.
108  * May optionally apply a cross-reference role to the type or the name
109    argument, but not the body.
110  * Can be configured to remove the bulleted list if there is only a
111    single entry.
112  * All items will be generated with the form "name (type) -- body"
113
114This is used for entries that are expected to be repeated and will have
115a name, a type, and a description. The QAPI domain uses this class for
116arguments, alternatives, and members. Wherever type names are referenced
117below, They must be a valid, documented type that will be
118cross-referenced in the HTML output; or one of the built-in JSON types
119(string, number, int, boolean, null, value, q_empty).
120
121
122``:feat:``
123----------
124
125Document a feature attached to a QAPI definition.
126
127:availability: This field list is available in the body of Command,
128               Event, Enum, Object and Alternate directives.
129:syntax: ``:feat name: Lorem ipsum, dolor sit amet...``
130:type: `sphinx.util.docfields.GroupedField
131       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.GroupedField.html?private=1>`_
132
133Example::
134
135   .. qapi:object:: BlockdevOptionsVirtioBlkVhostVdpa
136      :since: 7.2
137      :ifcond: CONFIG_BLKIO
138
139      Driver specific block device options for the virtio-blk-vhost-vdpa
140      backend.
141
142   :memb string path: path to the vhost-vdpa character device.
143   :feat fdset: Member ``path`` supports the special "/dev/fdset/N" path
144       (since 8.1)
145
146
147``:arg:``
148---------
149
150Document an argument to a QAPI command.
151
152:availability: This field list is only available in the body of the
153               Command directive.
154:syntax: ``:arg type name: description``
155:type: `sphinx.util.docfields.TypedField
156       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.TypedField.html?private=1>`_
157
158
159Example::
160
161   .. qapi:command:: job-pause
162      :since: 3.0
163
164      Pause an active job.
165
166      This command returns immediately after marking the active job for
167      pausing.  Pausing an already paused job is an error.
168
169      The job will pause as soon as possible, which means transitioning
170      into the PAUSED state if it was RUNNING, or into STANDBY if it was
171      READY.  The corresponding JOB_STATUS_CHANGE event will be emitted.
172
173      Cancelling a paused job automatically resumes it.
174
175      :arg string id: The job identifier.
176
177
178``:error:``
179-----------
180
181Document the error condition(s) of a QAPI command.
182
183:availability: This field list is only available in the body of the
184               Command directive.
185:syntax: ``:error: Lorem ipsum dolor sit amet ...``
186:type: `sphinx.util.docfields.Field
187       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.Field.html?private=1>`_
188
189The format of the :errors: field list description is free-form rST. The
190alternative spelling ":errors:" is also permitted, but strictly
191analogous.
192
193Example::
194
195   .. qapi:command:: block-job-set-speed
196      :since: 1.1
197
198      Set maximum speed for a background block operation.
199
200      This command can only be issued when there is an active block job.
201
202      Throttling can be disabled by setting the speed to 0.
203
204      :arg string device: The job identifier.  This used to be a device
205          name (hence the name of the parameter), but since QEMU 2.7 it
206          can have other values.
207      :arg int speed: the maximum speed, in bytes per second, or 0 for
208          unlimited.  Defaults to 0.
209      :error:
210          - If no background operation is active on this device,
211            DeviceNotActive
212
213
214``:return:``
215-------------
216
217Document the return type(s) and value(s) of a QAPI command.
218
219:availability: This field list is only available in the body of the
220               Command directive.
221:syntax: ``:return type: Lorem ipsum dolor sit amet ...``
222:type: `sphinx.util.docfields.GroupedField
223       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.GroupedField.html?private=1>`_
224
225
226Example::
227
228   .. qapi:command:: query-replay
229      :since: 5.2
230
231      Retrieve the record/replay information.  It includes current
232      instruction count which may be used for ``replay-break`` and
233      ``replay-seek`` commands.
234
235      :return ReplayInfo: record/replay information.
236
237      .. qmp-example::
238
239          -> { "execute": "query-replay" }
240          <- { "return": {
241                 "mode": "play", "filename": "log.rr", "icount": 220414 }
242             }
243
244
245``:return-nodesc:``
246-------------------
247
248Document the return type of a QAPI command, without an accompanying
249description.
250
251:availability: This field list is only available in the body of the
252               Command directive.
253:syntax: ``:return-nodesc: type``
254:type: `sphinx.util.docfields.Field
255       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.Field.html?private=1>`_
256
257
258Example::
259
260   .. qapi:command:: query-replay
261      :since: 5.2
262
263      Retrieve the record/replay information.  It includes current
264      instruction count which may be used for ``replay-break`` and
265      ``replay-seek`` commands.
266
267      :return-nodesc: ReplayInfo
268
269      .. qmp-example::
270
271          -> { "execute": "query-replay" }
272          <- { "return": {
273                 "mode": "play", "filename": "log.rr", "icount": 220414 }
274             }
275
276``:value:``
277-----------
278
279Document a possible value for a QAPI enum.
280
281:availability: This field list is only available in the body of the Enum
282               directive.
283:syntax: ``:value name: Lorem ipsum, dolor sit amet ...``
284:type: `sphinx.util.docfields.GroupedField
285       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.GroupedField.html?private=1>`_
286
287Example::
288
289   .. qapi:enum:: QapiErrorClass
290      :since: 1.2
291
292      QEMU error classes
293
294      :value GenericError: this is used for errors that don't require a specific
295          error class.  This should be the default case for most errors
296      :value CommandNotFound: the requested command has not been found
297      :value DeviceNotActive: a device has failed to be become active
298      :value DeviceNotFound: the requested device has not been found
299      :value KVMMissingCap: the requested operation can't be fulfilled because a
300          required KVM capability is missing
301
302
303``:alt:``
304------------
305
306Document a possible branch for a QAPI alternate.
307
308:availability: This field list is only available in the body of the
309               Alternate directive.
310:syntax: ``:alt type name: Lorem ipsum, dolor sit amet ...``
311:type: `sphinx.util.docfields.TypedField
312       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.TypedField.html?private=1>`_
313
314As a limitation of Sphinx, we must document the "name" of the branch in
315addition to the type, even though this information is not visible on the
316wire in the QMP protocol format. This limitation *may* be lifted at a
317future date.
318
319Example::
320
321   .. qapi:alternate:: StrOrNull
322      :since: 2.10
323
324      This is a string value or the explicit lack of a string (null
325      pointer in C).  Intended for cases when 'optional absent' already
326      has a different meaning.
327
328       :alt string s: the string value
329       :alt null n: no string value
330
331
332``:memb:``
333----------
334
335Document a member of an Event or Object.
336
337:availability: This field list is available in the body of Event or
338               Object directives.
339:syntax: ``:memb type name: Lorem ipsum, dolor sit amet ...``
340:type: `sphinx.util.docfields.TypedField
341       <https://pydoc.dev/sphinx/latest/sphinx.util.docfields.TypedField.html?private=1>`_
342
343This is fundamentally the same as ``:arg:`` and ``:alt:``, but uses the
344"Members" phrasing for Events and Objects (Structs and Unions).
345
346Example::
347
348   .. qapi:event:: JOB_STATUS_CHANGE
349      :since: 3.0
350
351      Emitted when a job transitions to a different status.
352
353      :memb string id: The job identifier
354      :memb JobStatus status: The new job status
355
356
357Arbitrary field lists
358---------------------
359
360Other field list names, while valid rST syntax, are prohibited inside of
361QAPI directives to help prevent accidental misspellings of info field
362list names. If you want to add a new arbitrary "non-value-added" field
363list to QAPI documentation, you must add the field name to the allow
364list in ``docs/conf.py``
365
366For example::
367
368   qapi_allowed_fields = {
369       "see also",
370   }
371
372Will allow you to add arbitrary field lists in QAPI directives::
373
374   .. qapi:command:: x-fake-command
375
376      :see also: Lorem ipsum, dolor sit amet ...
377
378.. _QAPI-domain-cross-references:
379
380Cross-references
381================
382
383Cross-reference `roles
384<https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html>`_
385in the QAPI domain are modeled closely after the `Python
386cross-referencing syntax
387<https://www.sphinx-doc.org/en/master/usage/domains/python.html#cross-referencing-python-objects>`_.
388
389QAPI definitions can be referenced using the standard `any
390<https://www.sphinx-doc.org/en/master/usage/referencing.html#role-any>`_
391role cross-reference syntax, such as with ```query-blockstats```.  In
392the event that disambiguation is needed, cross-references can also be
393written using a number of explicit cross-reference roles:
394
395* ``:qapi:mod:`block-core``` -- Reference a QAPI module. The link will
396  take you to the beginning of that section in the documentation.
397* ``:qapi:cmd:`query-block``` -- Reference a QAPI command.
398* ``:qapi:event:`JOB_STATUS_CHANGE``` -- Reference a QAPI event.
399* ``:qapi:enum:`QapiErrorClass``` -- Reference a QAPI enum.
400* ``:qapi:obj:`BlockdevOptionsVirtioBlkVhostVdpa`` -- Reference a QAPI
401  object (struct or union)
402* ``:qapi:alt:`StrOrNull``` -- Reference a QAPI alternate.
403* ``:qapi:type:`BlockDirtyInfo``` -- Reference *any* QAPI type; this
404  excludes modules, commands, and events.
405* ``:qapi:any:`block-job-set-speed``` -- Reference absolutely any QAPI entity.
406
407Type arguments in info field lists are converted into references as if
408you had used the ``:qapi:type:`` role. All of the special syntax below
409applies to both info field lists and standalone explicit
410cross-references.
411
412
413Type decorations
414----------------
415
416Type names in references can be surrounded by brackets, like
417``[typename]``, to indicate an array of that type.  The cross-reference
418will apply only to the type name between the brackets. For example;
419``:qapi:type:`[Qcow2BitmapInfoFlags]``` renders to:
420:qapi:type:`[QMP:Qcow2BitmapInfoFlags]`
421
422To indicate an optional argument/member in a field list, the type name
423can be suffixed with ``?``. The cross-reference will be transformed to
424"type, Optional" with the link applying only to the type name. For
425example; ``:qapi:type:`BitmapSyncMode?``` renders to:
426:qapi:type:`QMP:BitmapSyncMode?`
427
428
429Namespaces
430----------
431
432Mimicking the `Python domain target specification syntax
433<https://www.sphinx-doc.org/en/master/usage/domains/python.html#target-specification>`_,
434QAPI allows you to specify the fully qualified path for a data
435type.
436
437* A namespace can be explicitly provided;
438  e.g. ``:qapi:type:`QMP:BitmapSyncMode``
439* A module can be explicitly provided;
440  ``:qapi:type:`QMP:block-core.BitmapSyncMode``` will render to:
441  :qapi:type:`QMP:block-core.BitmapSyncMode`
442* If you don't want to display the "fully qualified" name, it can be
443  prefixed with a tilde; ``:qapi:type:`~QMP:block-core.BitmapSyncMode```
444  will render to: :qapi:type:`~QMP:block-core.BitmapSyncMode`
445
446
447Target resolution
448-----------------
449
450Any cross-reference to a QAPI type, whether using the ```any``` style of
451reference or the more explicit ```:qapi:any:`target``` syntax, allows
452for the presence or absence of either the namespace or module
453information.
454
455When absent, their value will be inferred from context by the presence
456of any ``qapi:namespace`` or ``qapi:module`` directives preceding the
457cross-reference.
458
459If no results are found when using the inferred values, other
460namespaces/modules will be searched as a last resort; but any explicitly
461provided values must always match in order to succeed.
462
463This allows for efficient cross-referencing with a minimum of syntax in
464the large majority of cases, but additional context or namespace markup
465may be required outside of the QAPI reference documents when linking to
466items that share a name across multiple documented QAPI schema.
467
468
469Custom link text
470----------------
471
472The name of a cross-reference link can be explicitly overridden like
473`most stock Sphinx references
474<https://www.sphinx-doc.org/en/master/usage/referencing.html#syntax>`_
475using the ``custom text <target>`` syntax.
476
477For example, ``:qapi:cmd:`Merge dirty bitmaps
478<block-dirty-bitmap-merge>``` will render as: :qapi:cmd:`Merge dirty
479bitmaps <QMP:block-dirty-bitmap-merge>`
480
481
482Directives
483==========
484
485The QAPI domain adds a number of custom directives for documenting
486various QAPI/QMP entities. The syntax is plain rST, and follows this
487general format::
488
489  .. qapi:directive:: argument
490     :option:
491     :another-option: with an argument
492
493     Content body, arbitrary rST is allowed here.
494
495
496Sphinx standard options
497-----------------------
498
499All QAPI directives inherit a number of `standard options
500<https://www.sphinx-doc.org/en/master/usage/domains/index.html#basic-markup>`_
501from Sphinx's ObjectDescription class.
502
503The dashed spellings of the below options were added in Sphinx 7.2, the
504undashed spellings are currently retained as aliases, but will be
505removed in a future version.
506
507* ``:no-index:`` and ``:noindex:`` -- Do not add this item into the
508  Index, and do not make it available for cross-referencing.
509* ``no-index-entry:`` and ``:noindexentry:`` -- Do not add this item
510  into the Index, but allow it to be cross-referenced.
511* ``no-contents-entry`` and ``:nocontentsentry:`` -- Exclude this item
512  from the Table of Contents.
513* ``no-typesetting`` -- Create TOC, Index and cross-referencing
514  entities, but don't actually display the content.
515
516
517QAPI standard options
518---------------------
519
520All QAPI directives -- *except* for namespace and module -- support
521these common options.
522
523* ``:namespace: name`` -- This option allows you to override the
524  namespace association of a given definition.
525* ``:module: modname`` -- Borrowed from the Python domain, this option allows
526  you to override the module association of a given definition.
527* ``:since: x.y`` -- Allows the documenting of "Since" information, which is
528  displayed in the signature bar.
529* ``:ifcond: CONDITION`` -- Allows the documenting of conditional availability
530  information, which is displayed in an eyecatch just below the
531  signature bar.
532* ``:deprecated:`` -- Adds an eyecatch just below the signature bar that
533  advertises that this definition is deprecated and should be avoided.
534* ``:unstable:`` -- Adds an eyecatch just below the signature bar that
535  advertises that this definition is unstable and should not be used in
536  production code.
537
538
539qapi:namespace
540--------------
541
542The ``qapi:namespace`` directive marks the start of a QAPI namespace. It
543does not take a content body, nor any options. All subsequent QAPI
544directives are associated with the most recent namespace. This affects
545the definition's "fully qualified name", allowing two different
546namespaces to create an otherwise identically named definition.
547
548This directive also influences how reference resolution works for any
549references that do not explicitly specify a namespace, so this directive
550can be used to nudge references into preferring targets from within that
551namespace.
552
553Example::
554
555   .. qapi:namespace:: QMP
556
557
558This directive has no visible effect.
559
560
561qapi:module
562-----------
563
564The ``qapi:module`` directive marks the start of a QAPI module. It may have
565a content body, but it can be omitted. All subsequent QAPI directives
566are associated with the most recent module; this effects their "fully
567qualified" name, but has no other effect.
568
569Example::
570
571   .. qapi:module:: block-core
572
573      Welcome to the block-core module!
574
575Will be rendered as:
576
577.. qapi:module:: block-core
578   :noindex:
579
580   Welcome to the block-core module!
581
582
583qapi:command
584------------
585
586This directive documents a QMP command. It may use any of the standard
587Sphinx or QAPI options, and the documentation body may contain
588``:arg:``, ``:feat:``, ``:error:``, or ``:return:`` info field list
589entries.
590
591Example::
592
593  .. qapi:command:: x-fake-command
594     :since: 42.0
595     :unstable:
596
597     This command is fake, so it can't hurt you!
598
599     :arg int foo: Your favorite number.
600     :arg string? bar: Your favorite season.
601     :return [string]: A lovely computer-written poem for you.
602
603
604Will be rendered as:
605
606  .. qapi:command:: x-fake-command
607     :noindex:
608     :since: 42.0
609     :unstable:
610
611     This command is fake, so it can't hurt you!
612
613     :arg int foo: Your favorite number.
614     :arg string? bar: Your favorite season.
615     :return [string]: A lovely computer-written poem for you.
616
617
618qapi:event
619----------
620
621This directive documents a QMP event. It may use any of the standard
622Sphinx or QAPI options, and the documentation body may contain
623``:memb:`` or ``:feat:`` info field list entries.
624
625Example::
626
627  .. qapi:event:: COMPUTER_IS_RUINED
628     :since: 0.1
629     :deprecated:
630
631     This event is emitted when your computer is *extremely* ruined.
632
633     :memb string reason: Diagnostics as to what caused your computer to
634        be ruined.
635     :feat sadness: When present, the diagnostic message will also
636        explain how sad the computer is as a result of your wrongdoings.
637
638Will be rendered as:
639
640.. qapi:event:: COMPUTER_IS_RUINED
641   :noindex:
642   :since: 0.1
643   :deprecated:
644
645   This event is emitted when your computer is *extremely* ruined.
646
647   :memb string reason: Diagnostics as to what caused your computer to
648      be ruined.
649   :feat sadness: When present, the diagnostic message will also explain
650      how sad the computer is as a result of your wrongdoings.
651
652
653qapi:enum
654---------
655
656This directive documents a QAPI enum. It may use any of the standard
657Sphinx or QAPI options, and the documentation body may contain
658``:value:`` or ``:feat:`` info field list entries.
659
660Example::
661
662  .. qapi:enum:: Mood
663     :ifcond: LIB_PERSONALITY
664
665     This enum represents your virtual machine's current mood!
666
667     :value Happy: Your VM is content and well-fed.
668     :value Hungry: Your VM needs food.
669     :value Melancholic: Your VM is experiencing existential angst.
670     :value Petulant: Your VM is throwing a temper tantrum.
671
672Will be rendered as:
673
674.. qapi:enum:: Mood
675   :noindex:
676   :ifcond: LIB_PERSONALITY
677
678   This enum represents your virtual machine's current mood!
679
680   :value Happy: Your VM is content and well-fed.
681   :value Hungry: Your VM needs food.
682   :value Melancholic: Your VM is experiencing existential angst.
683   :value Petulant: Your VM is throwing a temper tantrum.
684
685
686qapi:object
687-----------
688
689This directive documents a QAPI structure or union and represents a QMP
690object. It may use any of the standard Sphinx or QAPI options, and the
691documentation body may contain ``:memb:`` or ``:feat:`` info field list
692entries.
693
694Example::
695
696  .. qapi:object:: BigBlobOfStuff
697
698     This object has a bunch of disparate and unrelated things in it.
699
700     :memb int Birthday: Your birthday, represented in seconds since the
701                         UNIX epoch.
702     :memb [string] Fav-Foods: A list of your favorite foods.
703     :memb boolean? Bizarre-Docs: True if the documentation reference
704        should be strange.
705
706Will be rendered as:
707
708.. qapi:object:: BigBlobOfStuff
709   :noindex:
710
711   This object has a bunch of disparate and unrelated things in it.
712
713   :memb int Birthday: Your birthday, represented in seconds since the
714                       UNIX epoch.
715   :memb [string] Fav-Foods: A list of your favorite foods.
716   :memb boolean? Bizarre-Docs: True if the documentation reference
717      should be strange.
718
719
720qapi:alternate
721--------------
722
723This directive documents a QAPI alternate. It may use any of the
724standard Sphinx or QAPI options, and the documentation body may contain
725``:alt:`` or ``:feat:`` info field list entries.
726
727Example::
728
729  .. qapi:alternate:: ErrorCode
730
731     This alternate represents an Error Code from the VM.
732
733     :alt int ec: An error code, like the type you're used to.
734     :alt string em: An expletive-laced error message, if your
735        computer is feeling particularly cranky and tired of your
736        antics.
737
738Will be rendered as:
739
740.. qapi:alternate:: ErrorCode
741   :noindex:
742
743   This alternate represents an Error Code from the VM.
744
745   :alt int ec: An error code, like the type you're used to.
746   :alt string em: An expletive-laced error message, if your
747      computer is feeling particularly cranky and tired of your
748      antics.
749