Back to index

tetex-bin  3.0
Defines | Functions | Variables
comp_parse.c File Reference
#include <curses.priv.h>
#include <ctype.h>
#include <tic.h>
#include <term_entry.h>

Go to the source code of this file.

Defines

#define CUR   tp->

Functions

static void sanity_check2 (TERMTYPE *, bool)
static void sanity_check (TERMTYPE *)
 NCURSES_EXPORT_VAR (ENTRY *)
 _nc_free_entries (ENTRY *headp)
static char * force_bar (char *dst, char *src)
 _nc_entry_match (char *n1, char *n2)
 _nc_read_entry_source (FILE *fp, char *buf, int literal, bool silent, bool(*hook)(ENTRY *))
 _nc_resolve_uses2 (bool fullresolve, bool literal)
 _nc_resolve_uses (bool fullresolve)

Variables

NCURSES_IMPEXP void NCURSES_API(* _nc_check_termtype2 )(TERMTYPE *, bool) = sanity_check2
NCURSES_IMPEXP void NCURSES_API(* _nc_check_termtype )(TERMTYPE *) = sanity_check

Define Documentation

#define CUR   tp->

Definition at line 434 of file comp_parse.c.


Function Documentation

_nc_entry_match ( char *  n1,
char *  n2 
)

Definition at line 140 of file comp_parse.c.

{
    char *pstart, *qstart, *pend, *qend;
    char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2];

    n1 = force_bar(nc1, n1);
    n2 = force_bar(nc2, n2);

    for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1)
       for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1)
           if ((pend - pstart == qend - qstart)
              && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0)
              return (TRUE);

    return (FALSE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

_nc_free_entries ( ENTRY headp)

Definition at line 107 of file comp_parse.c.

{
    ENTRY *ep, *next;

    for (ep = headp; ep; ep = next) {
       _nc_free_termtype(&(ep->tterm));

       next = ep->next;

       free(ep);
       if (ep == _nc_head)
           _nc_head = 0;
       if (ep == _nc_tail)
           _nc_tail = 0;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

_nc_read_entry_source ( FILE fp,
char *  buf,
int  literal,
bool  silent,
bool(*)(ENTRY *)  hook 
)

Definition at line 165 of file comp_parse.c.

{
    ENTRY thisentry;
    bool oldsuppress = _nc_suppress_warnings;
    int immediate = 0;

    if (silent)
       _nc_suppress_warnings = TRUE;      /* shut the lexer up, too */

    _nc_reset_input(fp, buf);
    for (;;) {
       memset(&thisentry, 0, sizeof(thisentry));
       if (_nc_parse_entry(&thisentry, literal, silent) == ERR)
           break;
       if (!isalnum(UChar(thisentry.tterm.term_names[0])))
           _nc_err_abort("terminal names must start with letter or digit");

       /*
        * This can be used for immediate compilation of entries with no
        * use references to disk, so as to avoid chewing up a lot of
        * core when the resolution code could fetch entries off disk.
        */
       if (hook != NULLHOOK && (*hook) (&thisentry)) {
           immediate++;
       } else {
           enqueue(&thisentry);
           FreeIfNeeded(thisentry.tterm.Booleans);
           FreeIfNeeded(thisentry.tterm.Numbers);
           FreeIfNeeded(thisentry.tterm.Strings);
       }
    }

    if (_nc_tail) {
       /* set up the head pointer */
       for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last)
           continue;

       DEBUG(1, ("head = %s", _nc_head->tterm.term_names));
       DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names));
    }
#ifdef TRACE
    else if (!immediate)
       DEBUG(1, ("no entries parsed"));
#endif

    _nc_suppress_warnings = oldsuppress;
}

Here is the call graph for this function:

Here is the caller graph for this function:

_nc_resolve_uses ( bool  fullresolve)

Definition at line 422 of file comp_parse.c.

{
    return _nc_resolve_uses2(fullresolve, FALSE);
}

Here is the call graph for this function:

_nc_resolve_uses2 ( bool  fullresolve,
bool  literal 
)

Definition at line 217 of file comp_parse.c.

{
    ENTRY *qp, *rp, *lastread = 0;
    bool keepgoing;
    int i, unresolved, total_unresolved, multiples;

    DEBUG(2, ("RESOLUTION BEGINNING"));

    /*
     * Check for multiple occurrences of the same name.
     */
    multiples = 0;
    for_entry_list(qp) {
       int matchcount = 0;

       for_entry_list(rp) {
           if (qp > rp
              && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) {
              matchcount++;
              if (matchcount == 1) {
                  (void) fprintf(stderr, "Name collision between %s",
                               _nc_first_name(qp->tterm.term_names));
                  multiples++;
              }
              if (matchcount >= 1)
                  (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names));
           }
       }
       if (matchcount >= 1)
           (void) putc('\n', stderr);
    }
    if (multiples > 0)
       return (FALSE);

    DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES"));

    /*
     * First resolution stage: compute link pointers corresponding to names.
     */
    total_unresolved = 0;
    _nc_curr_col = -1;
    for_entry_list(qp) {
       unresolved = 0;
       for (i = 0; i < qp->nuses; i++) {
           bool foundit;
           char *child = _nc_first_name(qp->tterm.term_names);
           char *lookfor = qp->uses[i].name;
           long lookline = qp->uses[i].line;

           foundit = FALSE;

           _nc_set_type(child);

           /* first, try to resolve from in-core records */
           for_entry_list(rp) {
              if (rp != qp
                  && _nc_name_match(rp->tterm.term_names, lookfor, "|")) {
                  DEBUG(2, ("%s: resolving use=%s (in core)",
                           child, lookfor));

                  qp->uses[i].link = rp;
                  foundit = TRUE;
              }
           }

           /* if that didn't work, try to merge in a compiled entry */
           if (!foundit) {
              TERMTYPE thisterm;
              char filename[PATH_MAX];

              memset(&thisterm, 0, sizeof(thisterm));
              if (_nc_read_entry(lookfor, filename, &thisterm) == 1) {
                  DEBUG(2, ("%s: resolving use=%s (compiled)",
                           child, lookfor));

                  rp = typeMalloc(ENTRY, 1);
                  if (rp == 0)
                     _nc_err_abort(MSG_NO_MEMORY);
                  rp->tterm = thisterm;
                  rp->nuses = 0;
                  rp->next = lastread;
                  lastread = rp;

                  qp->uses[i].link = rp;
                  foundit = TRUE;
              }
           }

           /* no good, mark this one unresolvable and complain */
           if (!foundit) {
              unresolved++;
              total_unresolved++;

              _nc_curr_line = lookline;
              _nc_warning("resolution of use=%s failed", lookfor);
              qp->uses[i].link = 0;
           }
       }
    }
    if (total_unresolved) {
       /* free entries read in off disk */
       _nc_free_entries(lastread);
       return (FALSE);
    }

    DEBUG(2, ("NAME RESOLUTION COMPLETED OK"));

    /*
     * OK, at this point all (char *) references in `name' members
     * have been successfully converted to (ENTRY *) pointers in
     * `link' members.  Time to do the actual merges.
     */
    if (fullresolve) {
       do {
           TERMTYPE merged;

           keepgoing = FALSE;

           for_entry_list(qp) {
              if (qp->nuses > 0) {
                  DEBUG(2, ("%s: attempting merge",
                           _nc_first_name(qp->tterm.term_names)));
                  /*
                   * If any of the use entries we're looking for is
                   * incomplete, punt.  We'll catch this entry on a
                   * subsequent pass.
                   */
                  for (i = 0; i < qp->nuses; i++)
                     if (qp->uses[i].link->nuses) {
                         DEBUG(2, ("%s: use entry %d unresolved",
                                  _nc_first_name(qp->tterm.term_names), i));
                         goto incomplete;
                     }

                  /*
                     * First, make sure there's no garbage in the
                     * merge block.  as a side effect, copy into
                     * the merged entry the name field and string
                     * table pointer.
                   */
                  _nc_copy_termtype(&merged, &(qp->tterm));

                  /*
                   * Now merge in each use entry in the proper
                   * (reverse) order.
                   */
                  for (; qp->nuses; qp->nuses--)
                     _nc_merge_entry(&merged,
                                   &qp->uses[qp->nuses - 1].link->tterm);

                  /*
                   * Now merge in the original entry.
                   */
                  _nc_merge_entry(&merged, &qp->tterm);

                  /*
                   * Replace the original entry with the merged one.
                   */
                  FreeIfNeeded(qp->tterm.Booleans);
                  FreeIfNeeded(qp->tterm.Numbers);
                  FreeIfNeeded(qp->tterm.Strings);
                  qp->tterm = merged;
                  _nc_wrap_entry(qp, TRUE);

                  /*
                   * We know every entry is resolvable because name resolution
                   * didn't bomb.  So go back for another pass.
                   */
                  /* FALLTHRU */
                incomplete:
                  keepgoing = TRUE;
              }
           }
       } while
           (keepgoing);

       DEBUG(2, ("MERGES COMPLETED OK"));
    }

    /*
     * We'd like to free entries read in off disk at this point, but can't.
     * The merge_entry() code doesn't copy the strings in the use entries,
     * it just aliases them.  If this ever changes, do a
     * free_entries(lastread) here.
     */

    DEBUG(2, ("RESOLUTION FINISHED"));

    if (fullresolve)
       if (_nc_check_termtype != 0) {
           _nc_curr_col = -1;
           for_entry_list(qp) {
              _nc_curr_line = qp->startline;
              _nc_set_type(_nc_first_name(qp->tterm.term_names));
              _nc_check_termtype2(&qp->tterm, literal);
           }
           DEBUG(2, ("SANITY CHECK FINISHED"));
       }

    return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* force_bar ( char *  dst,
char *  src 
) [static]

Definition at line 126 of file comp_parse.c.

{
    if (strchr(src, '|') == 0) {
       size_t len = strlen(src);
       if (len > MAX_NAME_SIZE)
           len = MAX_NAME_SIZE;
       (void) strncpy(dst, src, len);
       (void) strcpy(dst + len, "|");
       src = dst;
    }
    return src;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 86 of file comp_parse.c.

{
    ENTRY *newp = _nc_copy_entry(ep);

    if (newp == 0)
       _nc_err_abort(MSG_NO_MEMORY);

    newp->last = _nc_tail;
    _nc_tail = newp;

    newp->next = 0;
    if (newp->last)
       newp->last->next = newp;
}

Here is the call graph for this function:

static void sanity_check ( TERMTYPE *  tp) [static]

Definition at line 497 of file comp_parse.c.

{
    sanity_check2(tp, FALSE);
}

Here is the call graph for this function:

static void sanity_check2 ( TERMTYPE *  tp,
bool  literal 
) [static]

Definition at line 437 of file comp_parse.c.

{
    if (!PRESENT(exit_attribute_mode)) {
#ifdef __UNUSED__           /* this casts too wide a net */
       bool terminal_entry = !strchr(tp->term_names, '+');
       if (terminal_entry &&
           (PRESENT(set_attributes)
            || PRESENT(enter_standout_mode)
            || PRESENT(enter_underline_mode)
            || PRESENT(enter_blink_mode)
            || PRESENT(enter_bold_mode)
            || PRESENT(enter_dim_mode)
            || PRESENT(enter_secure_mode)
            || PRESENT(enter_protected_mode)
            || PRESENT(enter_reverse_mode)))
           _nc_warning("no exit_attribute_mode");
#endif /* __UNUSED__ */
       PAIRED(enter_standout_mode, exit_standout_mode);
       PAIRED(enter_underline_mode, exit_underline_mode);
    }

    /* we do this check/fix in postprocess_termcap(), but some packagers
     * prefer to bypass it...
     */
    if (!literal) {
       if (acs_chars == 0
           && enter_alt_charset_mode != 0
           && exit_alt_charset_mode != 0)
           acs_chars = strdup(VT_ACSC);
       ANDMISSING(enter_alt_charset_mode, acs_chars);
       ANDMISSING(exit_alt_charset_mode, acs_chars);
    }

    /* listed in structure-member order of first argument */
    PAIRED(enter_alt_charset_mode, exit_alt_charset_mode);
    ANDMISSING(enter_blink_mode, exit_attribute_mode);
    ANDMISSING(enter_bold_mode, exit_attribute_mode);
    PAIRED(exit_ca_mode, enter_ca_mode);
    PAIRED(enter_delete_mode, exit_delete_mode);
    ANDMISSING(enter_dim_mode, exit_attribute_mode);
    PAIRED(enter_insert_mode, exit_insert_mode);
    ANDMISSING(enter_secure_mode, exit_attribute_mode);
    ANDMISSING(enter_protected_mode, exit_attribute_mode);
    ANDMISSING(enter_reverse_mode, exit_attribute_mode);
    PAIRED(from_status_line, to_status_line);
    PAIRED(meta_off, meta_on);

    PAIRED(prtr_on, prtr_off);
    PAIRED(save_cursor, restore_cursor);
    PAIRED(enter_xon_mode, exit_xon_mode);
    PAIRED(enter_am_mode, exit_am_mode);
    ANDMISSING(label_off, label_on);
#ifdef remove_clock
    PAIRED(display_clock, remove_clock);
#endif
    ANDMISSING(set_color_pair, initialize_pair);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 63 of file comp_parse.c.

Definition at line 59 of file comp_parse.c.