123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * COMPONENT_NAME: austext
- *
- * FUNCTIONS: austext_malloc
- * clean_wrap
- * cutnode_llist
- * free_llist
- * join_llists
- * merge_llist
- * nowstring
- * pop_llist
- * sort_llist
- * split_llist
- *
- * ORIGINS: 27
- *
- *
- * (C) COPYRIGHT International Business Machines Corp. 1991,1995
- * All Rights Reserved
- * Licensed Materials - Property of IBM
- * US Government Users Restricted Rights - Use, duplication or
- * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- /*************************** MSGUTIL.C *************************
- * $XConsortium: msgutil.c /main/9 1996/11/25 18:47:48 drk $
- * August 1991.
- * Utilites for generic manipulation of linked lists and binary trees.
- * All utilities require that the link fields be the first fields
- * in each structure. Also includes an error message mechanism
- * that is absolutely independent of user interface (UI)--
- * not even stdio is used. The trick is to append all
- * error/information messages to the end of a linked list that
- * eventually will be returned to the UI to be displayed
- * in whatever manner is appropriate. (However a generic stdio
- * print facility for the linked msglists is also provided
- * for dumping the list before crashing or when stdio is ok).
- *
- * With 2 exceptions, all messages should contain only
- * printable ascii characters and the space character.
- * Control characters and extended ascii graphics chars are verboten.
- * The exceptions are \n and \r, which are always permitted.
- *
- * The most common fatal error in opera and other text analysis
- * systems occurs when a memory allocation fails. Therefore
- * this module contains a generic 'safe malloc' function
- * which tests for failure and prints all outstanding messages
- * before exiting if malloc fails. It also uses DtSearchExit()
- * for the actual abort so other system dependent stuff can be
- * performed before going down.
- *
- * $Log$
- * Revision 2.4 1996/03/05 17:58:29 miker
- * Replace isspace() with ref to locale independent ascii_charmap[].
- *
- * Revision 2.3 1995/10/25 16:46:00 miker
- * Added prolog.
- *
- * Revision 2.2 1995/10/19 20:58:05 miker
- * Fix segfault in cleanwrap() if text contains single word > wraplen.
- *
- * Revision 2.1 1995/09/22 21:20:35 miker
- * Freeze DtSearch 0.1, AusText 2.1.8
- *
- * Revision 1.8 1995/09/05 18:21:23 miker
- * For DtSearch, rename and move universal msglist functions to msgs.c.
- */
- #include "SearchP.h"
- /****#include <ctype.h>****/
- #include <string.h>
- #include <stdlib.h>
- #define XOS_USE_NO_LOCKING
- #define X_INCLUDE_TIME_H
- #include <X11/Xos_r.h>
- #define PROGNAME "MSGUTIL"
- #define MAX_LINELEN 77
- #define MS_misc 1
- CMPLL compare_llist = NULL; /* global function pointer */
- /************************************************/
- /* */
- /* nowstring */
- /* */
- /************************************************/
- /* Returns ptr to static string where the current time
- * is formatted in human readable form. Used in audit
- * records, debugging logs, and error messages.
- */
- char *nowstring (time_t * now)
- {
- static char buf[128];
- time_t mynow;
- struct tm * time_ptr;
- _Xltimeparams localtime_buf;
- if (now == NULL) {
- now = &mynow;
- time (now);
- }
- time_ptr = _XLocaltime(now, localtime_buf);
- strftime (buf, sizeof (buf),
- CATGETS(dtsearch_catd, MS_misc, 2, "%Y/%m/%d,%H:%M:%S"),
- time_ptr);
- return buf;
- } /* nowstring() */
- /************************************************/
- /* */
- /* free_llist */
- /* */
- /************************************************/
- /* Frees storage for all items in an LLIST and
- * sets it top-of-list pointer to NULL. This works only for lists
- * created by append_msglist, append_textblobs, and other LLIST
- * structures where the data and the node itself
- * are allocated in one call to malloc().
- */
- void free_llist (LLIST ** llhead)
- {
- LLIST *next;
- LLIST *ll = *llhead;
- while (ll != NULL) {
- next = ll->link;
- free (ll);
- ll = next;
- }
- *llhead = NULL;
- return;
- } /* free_llist() */
- /************************************************/
- /* */
- /* join_llists */
- /* */
- /************************************************/
- /* Merges two list by appending sublist to end of mainlist,
- * then setting sublist to NULL. Originally either list can be NULL.
- * Mainlist is represented by ptr to ptr so it can be modified if NULL.
- * Sublist is ptr to ptr so it can be SET to NULL after join.
- * Method:
- * Init pp = ptr to first 'link' field in list,
- * i.e. the ptr to a ptr passed by the caller.
- * Usually this will be the addr of the top of the list pointer.
- * Then advance it to point to the last link in the list.
- *
- * Note that this function works for any LLIST including those
- * whose 'data' pointer is not allocated concurrently with the node.
- */
- void join_llists (LLIST ** mainlist, LLIST ** sublist)
- {
- LLIST **pp;
- for (pp = mainlist; *pp != NULL; pp = &((*pp)->link));
- *pp = *sublist;
- *sublist = NULL;
- return;
- } /* join_llists() */
- /************************************************/
- /* */
- /* pop_llist */
- /* */
- /************************************************/
- /* Detaches first node in an llist and returns it.
- * If *llistp is empty return NULL, else set *llistp to the link
- * cell of the first LLIST node on *llistp and return a pointer to
- * the first LLIST node on *llistp. Used mainly by merge_llist(),
- * which is itself called by sort_llist(), but can be called by
- * anyone needing to remove the first element of an llist.
- */
- LLIST *pop_llist (LLIST ** llistp)
- {
- LLIST *first_node = *llistp;
- if (first_node != NULL)
- *llistp = first_node->link;
- return first_node;
- } /* pop_llist() */
- /************************************************/
- /* */
- /* cutnode_llist */
- /* */
- /************************************************/
- /* Detaches any specified node in an llist and rejoins the
- * loose ends of the llist. *llistp may become NULL.
- * Returns NULL if *llistp is initially NULL or if node is not on llist,
- * else returns the detached node.
- */
- LLIST *cutnode_llist (LLIST * node, LLIST ** llistp)
- {
- LLIST **pp; /* link addr pointing to current node */
- for (pp = llistp; *pp != NULL; pp = &((*pp)->link)) {
- if (*pp == node)
- break;
- }
- if (*pp == NULL)
- return NULL;
- *pp = node->link; /* join the loose ends */
- return node;
- } /* cutnode_llist() */
- /************************************************/
- /* */
- /* split_llist */
- /* */
- /************************************************/
- /* Subroutine of sort_llist().
- * Find the middle node in lst. Set its 'link' pointer to NULL.
- * Return the remainder of lst, i.e. a pointer to the
- * next node after the middle node.
- */
- static LLIST *split_llist (LLIST * lst)
- {
- LLIST *tail;
- if (lst == NULL || lst->link)
- return lst;
- tail = lst->link;
- /* advance 'tail' to end of list, and advance 'lst' only half as often */
- while ((tail != NULL) && ((tail = tail->link) != NULL)) {
- lst = lst->link;
- tail = tail->link;
- }
- tail = lst->link;
- lst->link = NULL;
- return tail;
- } /* split_llist() */
- /************************************************/
- /* */
- /* merge_llist */
- /* */
- /************************************************/
- /* Subroutine of sort_llist(). Merges two sorted LLISTs together. */
- static LLIST *merge_llist (LLIST * l1, LLIST * l2)
- {
- LLIST *myqueue = NULL;
- LLIST *myend = NULL;
- LLIST *mynext;
- while ((l1 != NULL) && (l2 != NULL)) {
- /*
- * Perform ENQUEUE function. Next item popped off a list is
- * the next one in sorted order. It is added to END of
- * myqueue to maintain order. THIS IS WHERE THE ACTUAL SORT
- * COMPARE FUNCTION IS PERFORMED.
- */
- mynext = (compare_llist (l1, l2) < 0) ?
- pop_llist (&l1) : pop_llist (&l2);
- mynext->link = NULL;
- if (myqueue == NULL)
- myqueue = mynext;
- else
- myend->link = mynext;
- myend = mynext;
- }
- /* attach the remainder of whichever list is left to the end of queue */
- if (l1 != NULL)
- myend->link = l1;
- if (l2 != NULL)
- myend->link = l2;
- return myqueue;
- } /* merge_llist() */
- /************************************************/
- /* */
- /* sort_llist */
- /* */
- /************************************************/
- /* Sorts a list of LLIST structures and returns ptr to sorted list.
- * The basic idea is to sort by recursively splitting a list
- * into two equal halves and sorting each of those. The recursion
- * ends when there are only two small lists which are either
- * already sorted or are swapped. This sort rarely runs out
- * of stack space because each recursion cuts the list length in
- * half so there are at most 1 + log-N-to-the-base-2 items on the stack.
- * (e.g. 64,000 nodes = max stack depth of 16: 2**16 = 64K).
- *
- * The compare function accepts pointers to two LLIST structures.
- * It returns <0, =0, or >0 based on whether the first structure (left)
- * is <, =, or > the second (right) structure in sort order.
- * For efficiency's sake, a pointer to the compare function is placed
- * in the global variable 'compare_llist' before calling
- * sort_llist the first time, rather than continually
- * passing it to all these nested functions.
- */
- LLIST *sort_llist (LLIST * lst)
- {
- LLIST *lst2;
- if ((lst == NULL) || (lst->link == NULL))
- return lst;
- lst2 = split_llist (lst);
- return merge_llist (sort_llist (lst), sort_llist (lst2));
- } /* sort_llist() */
- /************************************************/
- /* */
- /* austext_malloc */
- /* */
- /************************************************/
- /* 'location' may be NULL. Last arg (formerly msglist) is isgnored.
- * Renamed from safe_malloc() to force compile errors if args not changed.
- */
- void *austext_malloc (size_t size, char *location, void *ignore)
- {
- static void *ptr;
- char *outofmem_msg;
- if ((ptr = malloc (size)) != NULL)
- return ptr;
- ptr = ((aa_argv0) ? aa_argv0 : "");
- if (location == NULL)
- location = CATGETS(dtsearch_catd, MS_misc, 1, "<null>");
- outofmem_msg = CATGETS(dtsearch_catd, MS_misc, 3,
- "*** %sOut of Memory at %s asking for %lu bytes! ***\n");
- fprintf (aa_stderr, outofmem_msg, ptr, location, size);
- fflush (aa_stderr);
- if (ausapi_msglist)
- fprintf (aa_stderr, "%s\n", DtSearchGetMessages ());
- fflush (aa_stderr);
- DtSearchExit (43);
- return NULL;
- } /* austext_malloc */
- /************************************************/
- /* */
- /* clean_wrap */
- /* */
- /************************************************/
- /* Utility which provides a way of breaking up long
- * messages which contain no control characters into lines
- * whose linefeed breaks occur at even word boundaries,
- * and whose lengths are controlled by the caller.
- * It should only be called when text itself may be
- * modified and may safely contain a linefeed (ascii 0x0A).
- * Converts a long text string into several lines by overlaying
- * the whitespace char nearest to the end of every line with \n.
- * Restarts length count if \n is found already within string.
- * Does nothing if passed wrap length = 0.
- * Does not append \n to end of string. Does not alter string length.
- * Returns total number of lines (\n's + trailing piece of last line),
- * or returns 0 if wraplen == 0.
- */
- int clean_wrap (char *string, int wraplen)
- {
- char *nlptr, *breakptr;
- int linecount = 0;
- if (wraplen <= 0)
- return 0;
- while (strlen (string) > wraplen) {
- breakptr = string + wraplen;
- /* Look for \n within the next wraplen */
- for (nlptr = string; nlptr < breakptr; nlptr++)
- if (*nlptr == '\n')
- break;
- if (nlptr < breakptr) {
- string = ++nlptr;
- goto LINE_DONE;
- }
- /* Otherwise back up to the first whitespace before last word */
- for (nlptr = breakptr - 1; nlptr > string; nlptr--)
- if (ascii_charmap[*nlptr] & WHITESPACE) {
- *nlptr = '\n';
- string = ++nlptr;
- goto LINE_DONE;
- }
- /* No whitespace at all in "text" before wraplen!
- * No choice but to overlay the last char.
- */
- *(--breakptr) = '\n';
- string = ++breakptr;
- LINE_DONE:
- linecount++;
- }
- /* Done wrapping. now just count remaining lines in string. */
- while (*string != 0)
- if (*string++ == '\n')
- linecount++;
- if (*(string - 1) != '\n')
- linecount++;
- return linecount;
- } /* clean_wrap() */
- /********************** MSGUTIL.C *************************/
|