123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- /*
- * 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: DtSearchFormatObjdate
- * DtSearchFreeResults
- * DtSearchGetMaxResults
- * DtSearchMergeResults
- * DtSearchSetMaxResults
- * DtSearchSortResults
- * DtSearchValidDateString
- * aa_check_initialization
- * aa_envars
- * aa_get_passwd
- * ditto_pop
- * ditto_sort
- * ditto_split
- * merge_by_date
- * merge_by_prox
- *
- * ORIGINS: 27
- *
- *
- * (C) COPYRIGHT International Business Machines Corp. 1995, 1996
- * 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.
- */
- /**************************** DTSRJOINT.C *************************
- * $XConsortium: dtsrjoint.c /main/5 1996/06/23 16:47:42 cde-ibm $
- * February 1995.
- * Split off of ausapi.c when I converted to client/server model.
- * Ausclt.c is virtual copy of ausapi functions in RPC client stub.
- * This module contains ausapi utilities that are common to both
- * sides (ie do not result in RPC call to server or require
- * access to real usrblk). My original version of this program
- * was called "aacom" for "ausapi common" but I renamed it to avoid
- * conflict with aacomm, the rpc/sockets communications module.
- *
- * $Log$
- * Revision 2.5 1996/04/10 19:52:16 miker
- * Added locale independent ISDIGIT macro. Changed function name
- * from aa_merge_dittolists to DtSearchMergeResults.
- *
- * Revision 2.4 1995/12/27 16:11:54 miker
- * Remove save_init_dbxxx globals for DtSearchReinit().
- *
- * Revision 2.3 1995/10/25 22:16:09 miker
- * Renamed from aajoint.c. Added prolog.
- *
- * Log: aajoint.c,v
- * Revision 2.2 1995/10/02 20:14:39 miker
- * DtSearch function name changes.
- * Added const to strdup() prototype for greater portability.
- * Changed to more uniform output format in DtSearchFormatObjdate().
- *
- * Revision 2.1 1995/09/22 15:18:08 miker
- * Freeze DtSearch 0.1, AusText 2.1.8
- *
- * Revision 1.3 1995/08/31 21:31:48 miker
- * Renames and minor changes for DtSearch.
- *
- * Revision 1.2 1995/06/22 18:01:09 miker
- * 2.1.6: RPC version no longer user specifiable. Removed aa_versnum etc.
- * Added aa_sort_dittolist, date sorting of hitlists by any client.
- */
- #include "SearchE.h"
- #include <termios.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #ifndef strdup
- extern char *strdup (const char *s);
- #endif
- #define PROGNAME "DTSRJOINT"
- #define ISDIGIT(c) ((ascii_charmap [(unsigned int) (c)] & NUMERAL) != 0)
- /*------------- GLOBALS VISIBLE TO CALLER -------------------*/
- /* see also globals.c */
- char **ausapi_dbnamesv = NULL; /* array of database names */
- int ausapi_dbnamesc = 0; /* size of dbnames array */
- int aa_maxhits = DtSrMAXHITS; /* num hits retnd after
- * srch */
- /*------------------- PRIVATE GLOBALS ---------------------*/
- int aa_is_initialized = FALSE;
- int aa_getnews_flag = 1;
- long save_init_switches = 0L;
- int ditsort_type = 0;
- /************************************************/
- /* */
- /* aa_check_initialization */
- /* */
- /************************************************/
- /* Confirms ausapi_init() was first function called. */
- void aa_check_initialization (void)
- {
- if (aa_is_initialized)
- return;
- fprintf (aa_stderr,
- CATGETS(dtsearch_catd, 2, 37,
- "%s First API function call must be DtSearchInit().\n"),
- PROGNAME"37");
- DtSearchExit (37);
- } /* aa_check_initialization() */
- /************************************************/
- /* */
- /* DtSearchValidDateString */
- /* */
- /************************************************/
- /* Subroutine of aa_both_valid_dates(), called once for each date string,
- * or can be called from user interface to validate a date string.
- * Converts passed date string into valid AusText DtSrObjdate.
- * Date string format: "[yy]yy [mm [dd]]",
- * 1, 2, or 3 numeric tokens separated by one
- * or more nonnumeric chars (whitespace, slashes, etc).
- * The first token is a complete year number integer yyyy
- * in the range 1900 <= yyyy <= 5995. If the first token contains
- * less than 4 digits it is presumed to be the number of years
- * since 1900. The month number is the second token mm,
- * in the range 1 - 12, and the third token dd is the day, 1 - 31.
- * If only two tokens are in the string they are presumed to
- * be year and month; the day is presumed to be to 1.
- * If only one token is in the string it is presumed to
- * be the year; the month is presumed to be 1 and the day
- * is presumed to be 1. NULL and empty strings are always
- * valid. They mean no date exclusion in the search
- * and this function returns objdate 0 for them.
- * Returns objdate on successful parse and conversion.
- * Returns -1 and err msg if date string is invalid.
- */
- DtSrObjdate DtSearchValidDateString (char *datestr)
- {
- DtSrObjdate objdate = 0L;
- char parsebuf[64];
- char *startp, *endp;
- int yy, mm, dd;
- int stop_parse = FALSE;
- char msgbuf[256];
- aa_check_initialization();
- if (datestr == NULL) /* null string is valid */
- return 0L;
- if (datestr[0] == 0) /* empty string is valid */
- return 0L;
- strncpy (parsebuf, datestr, sizeof (parsebuf));
- parsebuf[sizeof (parsebuf) - 1] = 0;
- /* yyyy */
- for (startp = parsebuf; *startp != 0 && !ISDIGIT(*startp); startp++);
- if (*startp == 0) { /* no numeric digits in string */
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"269 No numeric digits in string\n");
- #endif
- INVALID_DATESTR:
- sprintf (msgbuf,
- CATGETS(dtsearch_catd, 2, 115,
- "%s '%s' is invalid or incomplete date string.\n"
- "The correct format is '[yy]yy [mm [dd]]'."),
- PROGNAME"115", datestr);
- DtSearchAddMessage (msgbuf);
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"278 Returning objdate -1\n");
- fflush (aa_stderr);
- #endif
- return -1L;
- }
- for (endp = startp; ISDIGIT(*endp); endp++);
- if (*endp == 0) { /* mm and dd both missing */
- mm = 1;
- dd = 1;
- stop_parse = TRUE;
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"286 mm and dd both missing\n");
- #endif
- }
- *endp = 0;
- yy = atoi (startp);
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"293 yystr='%s' yy=%d\n", startp, yy);
- #endif
- if (strlen (startp) < 4)
- yy += 1900;
- if (yy < 1900 || yy > 5995)
- goto INVALID_DATESTR;
- if (stop_parse)
- goto DATESTR_OK;
- /* mm */
- for (startp = ++endp; *startp != 0 && !ISDIGIT(*startp); startp++);
- if (*startp == 0) { /* no mm in string */
- mm = 1;
- dd = 1;
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"309 No mm in string\n");
- #endif
- goto DATESTR_OK;
- }
- for (endp = startp; ISDIGIT(*endp); endp++);
- if (*endp == 0) { /* no dd in string */
- dd = 1;
- stop_parse = TRUE;
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"318 No dd in string\n");
- #endif
- }
- *endp = 0;
- mm = atoi (startp);
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"293 mmstr='%s' mm=%d\n", startp, mm);
- #endif
- if (mm < 1 || mm > 12)
- goto INVALID_DATESTR;
- if (stop_parse)
- goto DATESTR_OK;
- /* dd */
- for (startp = ++endp; *startp != 0 && !ISDIGIT(*startp); startp++);
- if (*startp == 0) { /* no dd in string */
- dd = 1;
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"336 No dd in string\n");
- #endif
- goto DATESTR_OK;
- }
- for (endp = startp; ISDIGIT(*endp); endp++);
- *endp = 0;
- dd = atoi (startp);
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr, PROGNAME"344 ddstr='%s' dd=%d\n", startp, dd);
- #endif
- if (dd < 1 || dd > 31)
- goto INVALID_DATESTR;
- DATESTR_OK:
- objdate = (yy - 1900) << 20 | (mm-1) << 16 | dd << 11;
- #ifdef DEBUG_VALDATE
- fprintf (aa_stderr,
- PROGNAME"352 Returning objdate %08lx, %d/%d/%d, %s\n",
- objdate, yy, mm, dd, objdate2fzkstr(objdate));
- fflush (aa_stderr);
- #endif
- return objdate;
- } /* DtSearchValidDateString() */
- /************************************************/
- /* */
- /* DtSearchFormatObjdate */
- /* */
- /************************************************/
- /* Converts objdate in hitlist to displayable string */
- char *DtSearchFormatObjdate (DtSrObjdate objdate)
- {
- static char datestr_buf[24];
- if (objdate == 0L)
- return "(undated)";
- strftime (datestr_buf, sizeof(datestr_buf), "%Y.%m.%d",
- objdate2tm (objdate));
- return datestr_buf;
- } /* DtSearchFormatObjdate() */
- /************************************************/
- /* */
- /* DtSearchGetMaxResults */
- /* DtSearchSetMaxResults */
- /* */
- /************************************************/
- int DtSearchGetMaxResults (void)
- { return aa_maxhits; }
- void DtSearchSetMaxResults (int newmax)
- { aa_maxhits = newmax; }
- /************************************************/
- /* */
- /* DtSearchFreeResults */
- /* */
- /************************************************/
- /* Frees storage allocated for the dittolist created
- * by DtSearchQuery(), and sets dittolist pointer to NULL.
- * Always returns DtSrOK.
- */
- int DtSearchFreeResults (DtSrResult ** dittolist)
- {
- free_llist ((LLIST **) dittolist);
- return DtSrOK;
- } /* DtSearchFreeResults() */
- /************************************************/
- /* */
- /* DtSearchMergeResults */
- /* */
- /************************************************/
- /* Merges one dittolist into another using proximity
- * for sort order. Sets 'src' dittolist pointer to NULL.
- * Does not change dittocount of either list, user must do that.
- * Returns DtSrOK on successful merge,
- * else returns DtSrERROR for programming error.
- * Formerly named aa_merge_dittolists.
- */
- int DtSearchMergeResults (DtSrResult **targ_list, DtSrResult **src_list)
- {
- DtSrResult *targ, *src, *nextsrc, **prevtargl;
- if (src_list == NULL || targ_list == NULL)
- return DtSrERROR;
- /* If there's no 'src' list, return with no changes.
- * In other words, merge was successful before we started.
- */
- if (*src_list == NULL)
- return DtSrOK;
- /* At this point we know there is a src_list.
- * If there's no targ_list, just swap the pointers.
- */
- if (*targ_list == NULL) {
- *targ_list = *src_list;
- *src_list = NULL;
- return DtSrOK;
- }
- /* We have two nonempty lists. Now do a real merge.
- * Insert src node into targ list only if it's
- * proximity is smaller. Otherwise just
- * advance to the next targ node.
- */
- src = *src_list; /* curr src_list node to compare */
- nextsrc = src->link; /* next src_list node to compare */
- targ = *targ_list; /* curr targ_list node to compare */
- prevtargl = targ_list; /* prev targ_list node link pointer */
- while (src != NULL && targ != NULL) {
- if (src->proximity < targ->proximity) {
- /* Insert src node into targ list */
- *prevtargl = src;
- src->link = targ;
- prevtargl = &src->link;
- src = nextsrc;
- if (src)
- nextsrc = src->link;
- }
- else {
- /* just advance to next targ node */
- prevtargl = &targ->link;
- targ = targ->link;
- }
- }
- /* If there's any src_list left,
- * just tack it onto the end of the targ_list.
- */
- if (src) {
- /* advance to end of targ_list */
- while (targ) {
- prevtargl = &targ->link;
- targ = targ->link;
- }
- *prevtargl = src;
- }
- *src_list = NULL;
- return DtSrOK;
- } /* DtSearchMergeResults() */
- /************************************************************
- * Aa_sort_dittolist(): basically a copy of ditto_sort() from engine,
- * but will sort on several different ditto fields
- * (currently only date fields implemented),
- * and is only used as convenience function on client/gui side.
- * The proximity field is always the minor sort key.
- * All functions with similar names to engine functions are static
- * in this module so they won't collide with same function in engine.
- * Performs a recursive split-merge sort on ditto lists.
- ************************************************************/
- /************************************************/
- /* */
- /* ditto_pop */
- /* */
- /************************************************/
- /* Subroutine of DtSearchSortResults().
- * Detaches first node in a list and returns it...
- * If *lst is empty return NULL, else set *lst to the link
- * cell of the first DtSrResult node on *lst and return a pointer to
- * the first DtSrResult node on *lst.
- */
- static DtSrResult *ditto_pop (DtSrResult ** lst)
- {
- DtSrResult *first_node;
- first_node = *lst;
- if (first_node != NULL)
- *lst = first_node->link;
- return first_node;
- } /* ditto_pop() */
- /************************************************/
- /* */
- /* ditto_split */
- /* */
- /************************************************/
- /* Subroutine of DtSearchSortResults().
- * Find the middle node in lst. Set its 'next' pointer to NULL.
- * Return the remainder of lst, i.e. a pointer to the
- * next node after the middle node.
- */
- static DtSrResult *ditto_split (DtSrResult * lst)
- {
- DtSrResult *tail = lst->link;
- if (lst == NULL || tail == NULL)
- return lst;
- /*
- * 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;
- } /* ditto_split() */
- /************************************************/
- /* */
- /* merge_by_prox */
- /* */
- /************************************************/
- /* Subroutine of DtSearchSortResults().
- * Merges two sorted DtSrResult lists together in proximity order.
- */
- static DtSrResult *merge_by_prox (DtSrResult * l1, DtSrResult * l2)
- {
- DtSrResult *myqueue = NULL;
- DtSrResult *myend = NULL;
- DtSrResult *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 = (l1->proximity < l2->proximity) ?
- ditto_pop (&l1) : ditto_pop (&l2);
- mynext->link = NULL;
- if (myqueue == NULL)
- myqueue = mynext;
- else
- myend->link = mynext;
- myend = mynext;
- }
- /*
- * Perform JOIN QUEUE function. Append entire list to end of
- * queue.
- */
- if (l1 != NULL)
- myend->link = l1;
- if (l2 != NULL)
- myend->link = l2;
- return myqueue;
- } /* merge_by_prox() */
- /************************************************/
- /* */
- /* merge_by_date */
- /* */
- /************************************************/
- /* Subroutine of DtSearchSortResults().
- * Merges two sorted DtSrResult lists together in objdate order.
- */
- static DtSrResult *merge_by_date (DtSrResult * l1, DtSrResult * l2)
- {
- DtSrResult *myqueue = NULL;
- DtSrResult *myend = NULL;
- DtSrResult *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.
- */
- if (l1->objdate == l2->objdate)
- mynext = (l1->proximity < l2->proximity) ?
- ditto_pop (&l1) : ditto_pop (&l2);
- else
- mynext = (l1->objdate > l2->objdate) ?
- ditto_pop (&l1) : ditto_pop (&l2);
- mynext->link = NULL;
- if (myqueue == NULL)
- myqueue = mynext;
- else
- myend->link = mynext;
- myend = mynext;
- }
- /*
- * Perform JOIN QUEUE function. Append entire list to end of
- * queue.
- */
- if (l1 != NULL)
- myend->link = l1;
- if (l2 != NULL)
- myend->link = l2;
- return myqueue;
- } /* merge_by_date() */
- /************************************************/
- /* */
- /* ditto_sort */
- /* */
- /************************************************/
- /* Subroutine of DtSearchSortResults().
- * Sorts a list of DtSrResult 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).
- */
- static DtSrResult *ditto_sort (DtSrResult * lst)
- {
- DtSrResult *lst2;
- if ((lst == NULL) || (lst->link == NULL))
- return lst;
- lst2 = ditto_split (lst);
- switch (ditsort_type) {
- case DtSrSORT_PROX:
- return merge_by_prox (ditto_sort (lst), ditto_sort (lst2));
- case DtSrSORT_DATE:
- return merge_by_date (ditto_sort (lst), ditto_sort (lst2));
- default:
- fprintf (aa_stderr, PROGNAME "525 Invalid Sort Type %d.\n",
- ditsort_type);
- DtSearchExit (32);
- }
- } /* ditto_sort() */
- /************************************************/
- /* */
- /* DtSearchSortResults */
- /* */
- /************************************************/
- /* Only publicly visible sort function.
- * DtSearchSortResults() was formerly named aa_sort_dittolist.
- */
- int DtSearchSortResults (DtSrResult ** dittolist, int sort_type)
- {
- switch (sort_type) {
- case DtSrSORT_PROX:
- case DtSrSORT_DATE:
- ditsort_type = sort_type;
- *dittolist = ditto_sort (*dittolist); /* recursive call */
- return DtSrOK;
- default:
- DtSearchAddMessage (PROGNAME "140 "
- "Program Error: Invalid sort type.");
- return DtSrERROR;
- }
- } /* DtSearchSortResults() */
- /**************************** DTSRJOINT.C *************************/
|