view lib-src/=timer.c @ 18212:3864648e9b4f

(bibtex-mode-map): Changed the binding of the C-TAB key, such that XEmacs will understand it, too. (bibtex-format-entry, bibtex-end-of-entry): Give specific error message if not on valid BibTeX entry. (bibtex-field-string-quoted): Small bug fix. Allow backslash followed by newline. (bibtex-reposition-window, bibtex-mark-entry): Two new functions, bound to M-C-l and M-C-h, respectively. (bibtex-reformat-previous-options, bibtex-reformat-previous-labels): New internal variables used by bibtex-reformat. (bibtex-clean-entry-hook): New hook to be called after entry has been cleaned. (bibtex-clean-entry): Run the hook bibtex-clean-entry-hook. (bibtex-entry-field-alist): Small bug fix. (bibtex-autokey-title-terminators): Made -- a terminator instead of ---. (bibtex-font-lock-keywords): Don't treat ALT prefixed entries as comments. (bibtex-entry): Fixed parameter list. This function is not intended to be called with required and optional fields as optional arguments anymore. (bibtex-generate-autokey): Now split into various small functions. (bibtex-autokey-names-stretch, bibtex-autokey-additional-names): New variables used by bibtex-generate-autokey. (bibtex-autokey-get-namefield, bibtex-autokey-get-names) (bibtex-autokey-demangle-name, bibtex-autokey-get-namelist) (bibtex-autokey-get-yearfield, bibtex-autokey-get-titlestring) (bibtex-autokey-get-titles, bibtex-autokey-get-titlelist): New helper functions for bibtex-generate-autokey. (bibtex-submit-bug-report): Report all variables. (bibtex-contline-indentation): New user option. (bibtex-entry-offset): Renamed from bibtex-entry-indentation. (bibtex-entry-field-alist): Used different order for some fields (as documented in btxdoc.tex). Changed one of the comment strings. (bibtex-mode-hook, bibtex-add-entry-hook): Add var doc. (bibtex-autokey-before-presentation-hook): New variable to be called before autokey presentation. (bibtex-generate-autokey): Call bibtex-autokey-before-presentation-hook. Doc fix. (bibtex-reference-key): Reincluded parentheses. Parentheses should be disallowed only in field constants. (bibtex-autokey-transcriptions): Fixed bug (two entries for `\o' while `\oe' entry was missing). (bibtex-entry-indentation): New variable to determine the indentation of all entries. (bibtex-move-outside-of-entry): Use `skip-chars-forward' instead of `re-search-forward'. (bibtex-beginning-of-first-entry, bibtex-beginning-of-last-entry): Renamed from beginning-of-first-bibtex-entry and beginning-of-last-bibtex-entry. Go to beginning of line, return point. (bibtex-do-auto-fill, bibtex-make-field, bibtex-entry) (bibtex-String, bibtex-Preamble): Respect `bibtex-entry-indentation'. (bibtex-beginning-of-entry, bibtex-end-of-entry): Make it work with indented entries. (bibtex-count-entries, bibtex-sort-buffer, bibtex-validate, bibtex-kill-entry, bibtex-reformat): Use return value from bibtex-beginning-of-first-entry. (bibtex-clean-entry): Use `bibtex-reference-maybe-empty-head' instead of a fixed string. (bibtex-beginning-of-entry, bibtex-end-of-entry): Now return point if called from a program. (bibtex-enclosing-field, bibtex-format-entry, bibtex-generate-autokey, bibtex-parse-keys, bibtex-mode, bibtex-ispell-entry, bibtex-narrow-to-entry, bibtex-sort-buffer, bibtex-find-entry-location, bibtex-validate, bibtex-clean-entry, bibtex-fill-entry): Use new return values of these functions. (bibtex-ispell-abstract): Bug fix (inherently by the change to bibtex-end-of-entry). (bibtex-field-history): New variable for history buffer of field name reading. (bibtex-make-field): Use completion. Object to completion are all standard fields defined for the current entry. Bound to `C-c C-f'. (bibtex-mode): Set `comment-start' and `comment-start-skip' to "@Comment ", `comment-column' to 0. (bibtex-autokey-transcriptions): New variable. (bibtex-autokey-name-change-strings) (bibtex-autokey-titleword-change-strings): Use bibtex-autokey-transcriptions as default value. (bibtex-find-entry-location): Handle empty buffer. (bibtex-entry-delimiters): New variable to determine if entries shall be delimited by braces or parentheses. (bibtex-entry-left-delimiter, bibtex-entry-right-delimiter): New helper functions. (bibtex-entry, bibtex-String, bibtex-Preamble): Respect `bibtex-entry-delimiters'. (bibtex-entry-format): Doc fix. (bibtex-reference-key, bibtex-field-const): Removed parentheses from allowed characters. (bibtex-end-of-entry): Better handling of incorrect preambles. (bibtex-validate): Small change to avoid reparsing of errors, if you enter `compile-goto-error' in compilation buffer. (bibtex-progress-message): New function to show progress of some long-lasting functions in BibTeX mode by indicating percentage of done work. (bibtex-progress-lastperc, bibtex-progress-lastmes) (bibtex-progress-interval): New internal variables for `bibtex-progress-message'. (bibtex-parse-keys, bibtex-reformat, bibtex-validate): Use new function `bibtex-progress-message'. (current-line): New helper function to calculate current linenumber. Something like this should really be defined somewhere else in Emacs. (bibtex-validate): Changed to show all errors in buffer in a `compilation mode' buffer. If there are syntax errors, it aborts after the syntax check, since higher-level check functions rely on the syntactical correctness of buffer. If called from another lisp function (as `bibtex-convert-alien') the return value shows whether validating has been successful. Fixed bug which made checking for absent required fields work incorrectly. (bibtex-parse-keys-timeout): Set to a value reasonable higher (twice as high) than `lazy-lock-stealth-time'. (bibtex-member-of-regexp, assoc-of-regexp): Small cosmetic changes. (bibtex-buffer-last-parsed-tick): Renamed from bibtex-buffer-last-parsed-for-keys-tick and made it really buffer-local (bug fix). (bibtex-parse-keys): Make it use bibtex-buffer-last-parsed-tick. (bibtex-parse-buffers-stealthily): New function which parses all BibTeX buffers if emacs has been idle an efficient amount of time. (bibtex-parse-idle-timer): New variable which stores whether idle timer for parsing already is installed. (bibtex-parse-keys): Make it callable verbosely. Returns now nil if it has been aborted. (bibtex-mode): Run the new function bibtex-parse-buffers-stealthily. (bibtex-generate-autokey): Changed the name part generation (bugfix). This function handles now correctly all three forms of BibTeX names, "First von Last", "von Last, First", "von Last, Jr, First". In every case the "Last" part is correctly extracted. If the "Last" part consists of more than one token only the first is used. Name fields spread over more than one line are no problem anymore. (bibtex-entry-format): Changed default value to exclude 'page-dashes. Modified documentation. (bibtex-autokey-name-change-strings) (bibtex-autokey-titleword-abbrevs) (bibtex-autokey-titleword-change-strings, bibtex-entry) (bibtex-validate): Doc fixes. (bibtex-mode-map): Bound `C-c $' to bibtex-ispell-abstract. (bibtex-generate-autokey): Changed documentation. Small modification in calculating title field. (bibtex-mode): Included bibtex-ispell-entry into the list of `interesting' functions. (bibtex-kill-field): Bug fix (killing of first field in entry yielded error). (bibtex-string-file-path): New variable which defines the path to search for bibtex-string-files. It defaults to contents of environment variable BIBINPUTS. (bibtex-mode): Use this variable. (bibtex-next-field, bibtex-find-text): Will now work with string entries as well. (bibtex-mode-map): bibtex-complete-key wasn't bound correctly. (bibtex-complete): Fixed bug (used string entries defined in buffer as object to completion). (Menu): Use easymenu. More menu items for `BibTeX-Edit' menu. Use nested menus. (bibtex-field-kill-ring-max) (bibtex-entry-kill-ring-max): Two new variables substituting bibtex-kill-ring-max. (bibtex-field-kill-ring, bibtex-entry-kill-ring): Two new variables substituting bibtex-kill-ring. (bibtex-field-kill-ring-yank-pointer) (bibtex-entry-kill-ring-yank-pointer): Two new variables substituting bibtex-kill-ring-yank-pointer. (bibtex-last-kill-command): New variable keeping the type of the last kill command. (bibtex-insert-current-kill): Clean distinction between the two BibTeX kill rings. (bibtex-kill-field): Use new variable bibtex-field-kill-ring. (bibtex-kill-entry): Use new variable bibtex-entry-kill-ring. (bibtex-kill-ring, bibtex-kill-ring-yank-pointer): New internal variables like kill-ring and kill-ring-yank-pointer, but bibtex-kill-ring holds fields or complete reference entries instead of raw strings. (bibtex-kill-ring-max): New user option similar to kill-ring-max. (bibtex-kill-field): Renamed from bibtex-delete-field again. It now supports the new variable bibtex-kill-ring. (bibtex-copy-field-as-kill, bibtex-kill-entry) (bibtex-copy-entry-as-kill, bibtex-yank, bibtex-yank-pop): New interactive functions, which work on the bibtex-kill-ring variable. (bibtex-insert-current-kill): New helper function to insert contents of bibtex-kill-ring in an appropriate way. (bibtex-make-field): New optional argument to tell the function if it was called by bibtex-yank. It operates slightly different then. (bibtex-find-text): New optional argument to tell the function if it was called by bibtex-make-field. It moves in this case to the end of the key if it was called on the reference head line. If it is called interactively on the head line, it works in an appropriate manner, too. (bibtex-enclosing-field): New optional argument to tell bibtex-enclosing-field not to print an error message if enclosing field isn't found, but to return nil in this case (t is returned otherwise). This is used by bibtex-find-text such that no error message is given if bibtex-find-text is called interactively in the key line of an entry. (bibtex-autokey-year-use-crossref-entry): New variable to determine if crossreferenced entry should be used for autokey generation, if year field of current entry is absent. (bibtex-generate-autokey): Use this new variable. (bibtex-include-OPTannote): Deleted (is set in bibtex-user-optional-fields). (bibtex-entry, bibtex-print-help-message): Removed support for bibtex-include-OPTannote. (bibtex-entry-format): New constant `inherit-booktitle' allowed. (bibtex-mode): Set value for font-lock-mark-block-function. (bibtex-font-lock-keywords): Changed to distinguish optional from ordinary fields. (bibtex-format-entry, bibtex-print-help-message) (bibtex-remove-OPT-or-ALT, bibtex-pop): Used simpler regexps. (bibtex-delete-field): Changed from bibtex-delete-optional-or-alternative-field. Deletes now mandatory fields as well. (bibtex-mode): Changed documentation. (bibtex-entry-type-history, bibtex-key-history): New variables to use own histories in BibTeX buffers. (bibtex-entry, bibtex-clean-entry, bibtex-String): Use these new variables. (bibtex-entry, bibtex-make-field): A function can now be used to generate a fields init string. (bibtex-include-OPTkey, bibtex-include-OPTannote) (bibtex-entry-field-alist): Changed documentation accordingly. (bibtex-mode): bibtex-parse-keys on start of mode is now abortable, too. (bibtex-entry, bibtex-complete-key, bibtex-String): If bibtex-keys isn't set correctly due to abortion of bibtex-parse-keys, this function is called now non-abortable. (bibtex-entry-field-alist): Small change in comments. (bibtex-find-entry-location): Bug fix: Insertion into completely empty buffer didn't work. (bibtex-user-optional-fields): Renamed from bibtex-mode-user-optional-fields. (bibtex-submit-bug-report, bibtex-entry, bibtex-print-help-message): Use bibtex-user-optional-fields. (bibtex-remove-delimiters): Bug fix: Only remove delimiting braces and not those inside fields. (skip-to-valid-bibtex-entry, bibtex-parse-keys) (bibtex-end-of-entry, bibtex-validate, bibtex-reformat): Calculate complex regexps outside of loops. (bibtex-mode): Changed documentation on how to convert third party buffers. (bibtex-convert-alien): New function to convert a buffer not created by BibTeX mode to a format, whichs enables all features of BibTeX mode. (bibtex-mode): Small bug fix for call to bibtex-parse-keys. (bibtex-mode): Bug fix for using bibtex-parse-keys. (bibtex-mode): Used other policy to initiate the first call of bibtex-parse-keys. This avoids unnecessary double call if Font Lock mode is chosen for buffer at startup. (bibtex-String, bibtex-Preamble): Renamed from bibtex-string and bibtex-preamble. (bibtex-String): If bibtex-maintain-sorted-entries and bibtex-sort-ignore-string-entries are both non-nil, read string key from minibuffer (with completion) and insert entry at correct location (as for normal entries). (bibtex-autokey-titleword-first-ignore) (bibtex-autokey-titleword-abbrevs): Changed documentation: case of regexps doesn't matter anymore. (bibtex-field-const, bibtex-reference-key): Simplified to not contain uppercase letters. (member-of-regexp, assoc-of-regexp): Ignore case of regexp. (map-bibtex-entries): Call function not for every syntactical correct entry, but only for entries with known type. (map-bibtex-entries, skip-to-valid-bibtex-entry) (bibtex-flash-head, bibtex-enclosing-field) (bibtex-enclosing-reference-maybe-empty-head, bibtex-format-entry) (bibtex-autokey-change, bibtex-generate-autokey, bibtex-parse-keys) (bibtex-ispell-abstract, bibtex-sort-buffer) (bibtex-find-entry-location, bibtex-validate, bibtex-remove-delimiters) (bibtex-delete-optional-or-alternative-field, bibtex-pop) (bibtex-clean-entry, bibtex-print-help-message): Make them work regardless of user's value of case-fold-search. (bibtex-generate-autokey): Use bibtex-cfield for generating the year field regexp. (bibtex-parse-keys): Only gather keys of known (and not of syntactical correct) entries. (bibtex-end-of-entry): Only report an "unknown entry" message if called interactively. (bibtex-sort-ignore-string-entries): Renamed back from bibtex-sort-ignore-string-and-preamble. Of course, preambles are always ignored, since they have no key at all. (bibtex-string): Slightly less complex regexp. (skip-to-valid-bibtex-entry): New helper function to skip forward (or backward) to beginning of next syntactical correct known BibTeX entry, if not already there. Respects bibtex-sort-ignore-string-entries. (map-bibtex-entries): Bug fix: It wasn't called for string entries even if bibtex-sort-ignore-string-entries was nil. (beginning-of-last-bibtex-entry): New helper function to go to last entry in buffer. (bibtex-end-of-entry): Bug fix: Now works with string and preamble entries as well. (bibtex-sort-buffer): Renamed from bibtex-sort-entries. Simplified by using new function skip-to-valid-bibtex-entry. Now only known entries are checked. (bibtex-find-entry-location): Simplified by using new functions skip-to-valid-bibtex-entry and beginning-of-last-bibtex-entry. Only known entries are used to determine location. (bibtex-validate): Now checks string entries, too. (bibtex-move-outside-of-entry): Don't use forward-paragraph, but bibtex-end-of-entry. (bibtex-end-of-entry): Don't use forward-sexp anymore, since this fails on entries with non-escaped souble-quotes. Use search-bibtex-reference instead (though it is slower, it is more reliable). (bibtex-ispell-abstract): Use normal regexps created by bibtex-cfield instead of special ones. (beginning-of-first-bibtex-entry): No warning on empty buffer. (bibtex-validate): Bug fix. Syntactical check didn't work, since due to a bug all entries were simply skipped. (bibtex-mode): Doc fix. (bibtex-delete-optional-or-alternative-field): Renamed from bibtex-kill-optional-or-alternative-field. (bibtex-delete-optional-or-alternative-field, bibtex-empty-field): Use delete-region, not kill-region. (bibtex-clean-entry): New second argument called-by-reformat indicates if bibtex-clean-entry was called by reformat. Don't try to find correct buffer position for newly generated key and don't call bibtex-parse-keys in this case. (map-bibtex-entries): Bugfix (missed first entry in buffer, died on entries with `@' in other than first column). (beginning-of-first-bibtex-entry, bibtex-format-entry) (bibtex-beginning-of-entry, bibtex-validate, bibtex-clean-entry): Changed to allow BibTeX entries to start in a column different from 1 (but still for speed reasons only whitespace is allowed prior to the `@' on the same line. (map-bibtex-entries): Call it for known BibTeX entries only. This allows entries as @Comment{...} which follow no specific structure without breaking the validation functions. (bibtex-validate): Check syntactical structure for known entries only. (bibtex-autokey-abbrev): Sped up and changed to allow a length of zero. (bibtex-entry-format): Remove option `month-strings'. (bibtex-validate): If given a prefix argument, check for questionable month fields. (bibtex-generate-autokey): Use normal regexps created by bibtex-cfield instead of special ones. (bibtex-hide-entry-bodies): Sped up by using subst-char-in-region instead of using replace-regexp or replace-match. (bibtex-find-entry-location): A bug had been introduced by using search-bibtex-reference instead of re-search-forward (fixed). (bibtex-field-delimiters): Renamed from bibtex-field-delimiter. (bibtex-entry-format): Constant empty-opts renamed to empty-opts-or-alts. (bibtex-remove-delimiters): Renamed from bibtex-remove-double-quotes-or-braces. (bibtex-reformat): New function. (bibtex-fill-entry): New function to refill entry. (bibtex-mode-map): Defined key for bibtex-fill-entry. (bibtex-field-delimiter): Substitutes variables bibtex-field-left-delimiter and bibtex-field-right-delimiter. (bibtex-field-left-delimiter, bibtex-field-right-delimiter): New helper functions. (bibtex-make-field, bibtex-pop): Use new variable bibtex-field-delimiter. (bibtex-empty-field, bibtex-string): Use new functions bibtex-field-left-delimiter and bibtex-field-right-delimiter. (bibtex-predefined-month-strings): New variable. (bibtex-predefined-strings): Use bibtex-predefined-month-strings. (bibtex-submit-bug-report): Use new variables bibtex-field-delimiter and bibtex-predefined-month-strings. (bibtex-entry-format): Substitutes variable bibtex-clean-entry-zap-empty-opts-or-alts. Various types of formatting options are available (see variable documentation). (bibtex-format-entry): New function doing the formatting of entries. Taken from bibtex-clean-entry and enhanced to support new variable bibtex-entry-format. (delete-whitespace): New helper function used by bibtex-format-entry. (bibtex-clean-entry): Call new function bibtex-format-entry. (bibtex-submit-bug-report): Use bibtex-entry-format instead of bibtex-clean-entry-zap-empty-opts-or-alts. (bibtex-do-auto-fill): New function to perform auto-filling in BibTeX mode. In fact, this is the old function bibtex-auto-fill-function. (bibtex-mode): Don't set fill-prefix anymore, but use new function bibtex-do-auto-fill. (bibtex-find-entry-location): Fixed bug (when bibtex-maintain-sorted-entries was non-nil, an entry with a key greater than all other keys wasn't inserted in the correct place). (bibtex-mode): Don't use bibtex-auto-fill-function anymore, but use directly variable fill-prefix. (bibtex-find-entry-location): Fixed bug (on duplicate keys, point must move to beginning of entry, so that bibtex-entry works correctly). (bibtex-complete): Fixed bug (parameter string-list was mistakenly altered by the function itself). (bibtex-mode-map): Bind bibtex-complete-key to C-TAB. (bibtex-validate): Renamed from bibtex-validate-buffer since it can acts on region if active. Use search-bibtex-reference. (search-bibtex-reference): New function to be used in places where prior a re-search-{forward|backward} for bibtex-reference or something alike was used. This function is necessary due to the new limit of failure stack size in 19.32 and above. (bibtex-enclosing-reference-maybe-empty-head) (bibtex-sort-entries, bibtex-find-entry-location, bibtex-validate): Use new function search-bibtex-reference. (bibtex-pop, bibtex-clean-entry): Small change due to change in bibtex-enclosing-reference-maybe-empty-head. (bibtex-reference-infix, bibtex-reference-postfix): New constants necessary due to splitting bibtex-reference. (bibtex-reference): Deleted. (bibtex-type-in-reference, skip-whitespace-and-comments): Deleted. (bibtex-mode): Don't turn auto-fill-mode on. Use new variable normal-auto-fill-function. (bibtex-field-string): Simplified. (bibtex-mode-syntax-table): Changed syntax of double-quote back to quote syntax. (bibtex-complete): New generic function for interface functions bibtex-complete-string and bibtex-complete-key. (bibtex-complete-key): New function. (bibtex-sort-ignore-string-and-preamble): Renamed from bibtex-sort-ignore-string-entries. (map-bibtex-entries): Use bibtex-sort-ignore-string-and-preamble and ignore preamble entries as well. (bibtex-mode, bibtex-submit-bug-report, bibtex-sort-entries): Use bibtex-sort-ignore-string-and-preamble. (bibtex-count-entries): New function to count entries in buffer or region. (bibtex-comma-after-last-field): New variable to decide if comma should be inserted at end of last field. (bibtex-entry): Support new variable bibtex-comma-after-last-field. (bibtex-field-indentation, bibtex-text-indentation): Two new user options (replacing the former constants bibtex-field-alignment and bibtex-text-alignment). (bibtex-align-at-equal-sign): New user option. (bibtex-auto-fill-function, bibtex-make-field) (bibtex-remove-OPT-or-ALT, bibtex-clean-entry): Support new variables. (bibtex-validate-buffer): Now only checks region if mark is active. With optional argument checks if required fields are missing, too. (bibtex-mode): Added support for imenu. (bibtex-entry-field-alist) (bibtex-mode-user-optional-fields): Modified syntax to allow preinitialization of fields. (bibtex-make-field, bibtex-make-optional-field): Support preinitialization of fields. (bibtex-autokey-prefix-string) (bibtex-autokey-preserve-case): New variables to support bibtex-generate-autokey. (bibtex-generate-autokey): Use new variables. (bibtex-field-const, bibtex-reference-type) (bibtex-reference-key): Changed to match the (according to Oren Patashnik) allowed characters. (bibtex-clean-entry-zap-empty-opts-or-alts): Renamed from bibtex-clean-entry-zap-empty-opts. (bibtex-entry-field-alist): Slightly modified syntax to support alternative fields needed for Book and InBook references. (bibtex-font-lock-keywords, bibtex-print-help-message) (bibtex-make-field, bibtex-pop, bibtex-clean-entry): Support ALT prefixed entries. (bibtex-mode): Documented new ALT prefixed fields. (bibtex-make-optional-field): Modified to give only field name as arg to bibtex-make-field. (bibtex-remove-OPT-or-ALT, bibtex-kill-optional-or-alternative-field): Renamed from bibtex-remove-OPT and bibtex-kill-optional-field, respectively. Modified to support ALT prefixes. (bibtex-enclosing-field, bibtex-print-help-message): Speed up things by not using bibtex-enclosing-regexp anymore. (bibtex-enclosing-regexp): Function deleted.
author Richard M. Stallman <rms@gnu.org>
date Tue, 10 Jun 1997 17:58:43 +0000
parents dd3b83e4ceb0
children
line wrap: on
line source

/* timer.c --- daemon to provide a tagged interval timer service

   This little daemon runs forever waiting for commands to schedule events.
   SIGALRM causes
   it to check its queue for events attached to the current second; if
   one is found, its label is written to stdout.  SIGTERM causes it to
   terminate, printing a list of pending events.

   This program is intended to be used with the lisp package called
   timer.el.  The first such program was written anonymously in 1990.
   This version was documented and rewritten for portability by
   esr@snark.thyrsus.com, Aug 7 1992.  */

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>  /* time_t */

#include <../src/config.h>
#undef read

#ifdef LINUX
/* Perhaps this is correct unconditionally.  */
#undef signal
#endif
#ifdef _CX_UX
/* I agree with the comment above, this probably should be unconditional (it
 * is already unconditional in a couple of other files in this directory),
 * but in the spirit of minimizing the effects of my port, I am making it
 * conditional on _CX_UX.
 */
#undef signal
#endif


extern int errno;
extern char *strerror ();
extern time_t time ();

/*
 * The field separator for input.  This character shouldn't occur in dates,
 * and should be printable so event strings are readable by people.
 */
#define FS '@'

struct event
  {
    char *token;
    time_t reply_at;
  };
int events_size;		/* How many slots have we allocated?  */
int num_events;			/* How many are actually scheduled?  */
struct event *events;		/* events[0 .. num_events-1] are the
				   valid events.  */

char *pname;      /* program name for error messages */

/* This buffer is used for reading commands.
   We make it longer when necessary, but we never free it.  */
char *buf;
/* This is the allocated size of buf.  */
int buf_size;

/* Non-zero means don't handle an alarm now;
   instead, just set alarm_deferred if an alarm happens.
   We set this around parts of the program that call malloc and free.  */
int defer_alarms;

/* Non-zero if an alarm came in during the reading of a command.  */
int alarm_deferred;

/* Schedule one event, and arrange an alarm for it.
   STR is a string of two fields separated by FS.
   First field is string for get_date, saying when to wake-up.
   Second field is a token to identify the request.  */

void
schedule (str)
     char *str;
{
  extern time_t get_date ();
  extern char *strcpy ();
  time_t now;
  register char *p;
  static struct event *ep;
  
  /* check entry format */
  for (p = str; *p && *p != FS; p++)
    continue;
  if (!*p)
    {
      fprintf (stderr, "%s: bad input format: %s\n", pname, str);
      return;
    }
  *p++ = 0;
  
  /* allocate an event slot */
  ep = events + num_events;

  /* If the event array is full, stretch it.  After stretching, we know
     that ep will be pointing to an available event spot.  */
  if (ep == events + events_size)
    {
      int old_size = events_size;

      events_size *= 2;
      events = ((struct event *)
		realloc (events, events_size * sizeof (struct event)));
      if (! events)
	{
	  fprintf (stderr, "%s: virtual memory exhausted.\n", pname);
	  /* Since there is so much virtual memory, and running out
	     almost surely means something is very very wrong,
	     it is best to exit rather than continue.  */
	  exit (1);
	}

      while (old_size < events_size)
	events[old_size++].token = NULL;
    }

  /* Don't allow users to schedule events in past time.  */
  ep->reply_at = get_date (str, NULL);
  if (ep->reply_at - time (&now) < 0)
    {
      fprintf (stderr, "%s: bad time spec: %s%c%s\n", pname, str, FS, p);
      return;
    }

  /* save the event description */
  ep->token = (char *) malloc ((unsigned) strlen (p) + 1);
  if (! ep->token)
    {
      fprintf (stderr, "%s: malloc %s: %s%c%s\n",
	       pname, strerror (errno), str, FS, p);
      return;
    }

  strcpy (ep->token, p);
  num_events++;
}

/* Print the notification for the alarmed event just arrived if any,
   and schedule an alarm for the next event if any.  */

void
notify ()
{
  time_t now, tdiff, waitfor = -1;
  register struct event *ep;

  /* Inhibit interference with alarms while changing global vars.  */
  defer_alarms = 1;
  alarm_deferred = 0;

  now = time ((time_t *) NULL);

  for (ep = events; ep < events + num_events; ep++)
    /* Are any events ready to fire?  */
    if (ep->reply_at <= now)
      {
	fputs (ep->token, stdout);
	putc ('\n', stdout);
	fflush (stdout);
	free (ep->token);

	/* We now have a hole in the event array; fill it with the last
	   event.  */
	ep->token = events[num_events - 1].token;
	ep->reply_at = events[num_events - 1].reply_at;
	num_events--;

	/* We ought to scan this event again.  */
	ep--;
      }
    else
      {
	/* next timeout should be the soonest of any remaining */
	if ((tdiff = ep->reply_at - now) < waitfor || waitfor < 0)
	  waitfor = (long)tdiff;
      }

  /* If there are no more events, we needn't bother setting an alarm.  */
  if (num_events > 0)
    alarm (waitfor);

  /* Now check if there was another alarm
     while we were handling an explicit request.  */
  defer_alarms = 0;
  if (alarm_deferred)
    notify ();
  alarm_deferred = 0;
}

/* Read one command from command from standard input
   and schedule the event for it.  */

void
getevent ()
{
  int i;

  /* In principle the itimer should be disabled on entry to this
     function, but it really doesn't make any important difference
     if it isn't.  */

  if (buf == 0)
    {
      buf_size = 80;
      buf = (char *) malloc (buf_size);
    }

  /* Read a line from standard input, expanding buf if it is too short
     to hold the line.  */
  for (i = 0; ; i++)
    {
      char c;
      int nread;

      if (i >= buf_size)
	{
	  buf_size *= 2;
	  alarm_deferred = 0;
	  defer_alarms = 1;
	  buf = (char *) realloc (buf, buf_size);
	  defer_alarms = 0;
	  if (alarm_deferred)
	    notify ();
	  alarm_deferred = 0;
	}

      /* Read one character into c.  */
      while (1)
	{
	  nread = read (fileno (stdin), &c, 1);

	  /* Retry after transient error.  */
	  if (nread < 0
	      && (1
#ifdef EINTR
		  || errno == EINTR
#endif
#ifdef EAGAIN
		  || errno == EAGAIN
#endif
		  ))
	    continue;

	  /* Report serious errors.  */
	  if (nread < 0)
	    {
	      perror ("read");
	      exit (1);
	    }

	  /* On eof, exit.  */
	  if (nread == 0)
	    exit (0);

	  break;
	}

      if (c == '\n')
	{
	  buf[i] = '\0';
	  break;
	}

      buf[i] = c;
    }

  /* Register the event.  */
  alarm_deferred = 0;
  defer_alarms = 1;
  schedule (buf);
  defer_alarms = 0;
  notify ();
  alarm_deferred = 0;
}

/* Handle incoming signal SIG.  */

SIGTYPE
sigcatch (sig)
     int sig;
{
  struct event *ep;

  /* required on older UNIXes; harmless on newer ones */
  signal (sig, sigcatch);

  switch (sig)
    {
    case SIGALRM:
      if (defer_alarms)
	alarm_deferred = 1;
      else
	notify ();
      break;
    case SIGTERM:
      fprintf (stderr, "Events still queued:\n");
      for (ep = events; ep < events + num_events; ep++)
	fprintf (stderr, "%d = %ld @ %s\n",
		 ep - events, ep->reply_at, ep->token);
      exit (0);
      break;
    }
}

/*ARGSUSED*/
int
main (argc, argv)
     int argc;
     char **argv;
{
  for (pname = argv[0] + strlen (argv[0]);
       *pname != '/' && pname != argv[0];
       pname--);
  if (*pname == '/')
    pname++;

  events_size = 16;
  events = ((struct event *) malloc (events_size * sizeof (*events)));
  num_events = 0;

  signal (SIGALRM, sigcatch);
  signal (SIGTERM, sigcatch);

  /* Loop reading commands from standard input
     and scheduling alarms accordingly.
     The alarms are handled asynchronously, while we wait for commands.  */
  while (1)
    getevent ();
}

#ifndef HAVE_STRERROR
char *
strerror (errnum)
     int errnum;
{
  extern char *sys_errlist[];
  extern int sys_nerr;

  if (errnum >= 0 && errnum < sys_nerr)
    return sys_errlist[errnum];
  return (char *) "Unknown error";
}

#endif /* ! HAVE_STRERROR */

long *
xmalloc (size)
     int size;
{
  register long *val;

  val = (long *) malloc (size);

  if (!val && size)
    {
      fprintf (stderr, "timer: virtual memory exceeded\n");
      exit (1);
    }
    
  return val;
}

/* timer.c ends here */