/* outer.c outer_brev version 1.0 came from outer.c version 2.5, JGOFS 1.5 release (as of 10 Jan 98). Renamed back to outer as of summer 06, approx vers outer_brev 2.1. Seemed appropriate to set version of newly-returned outer higher than 2.5... Incompatibilities 1) outer_brev variable names may not include spaces or percent signs. 2) Non-numeric data values (including "nd") cannot be selected with numeric operators 3) When clicking on a datum to use it as a selection for the next level, comparisons are done as strings instead of numbers 4) Rely on program exit to free dynamically allocated memory */ #define OUTER_VERSION "outer version 3.4 11 Aug 2010" /* 11 Aug 10 v 3.4 WJS Bug fix: code to remove empty levels apparently incorrect from inception (outer 3.0). Same levels of original object could appear on different levels of output object. Also, there could be data at a level w/o vars at that level. Ick! "Things worked first time through", so manifestation seems to be datasets truncated after said "first time through" [Begin outer 3.4] 5 Feb 10 v 3.3 WJS Put extended URL into OOserver link. Should allow OOserver to use the correct INFOSERVER [Begin outer 3.3] 21 May 09 v 3.2 WJS Bug fix: do something reasonable w/display of attribute lists in "flat" output. While at it, check buffer overflows, parametrize some stuff, and even do things a bit more efficiently [needs outer.h 1.5c] 15 May 09 v 3.2 WJS Get rid of precison-dependent stuff Make a global variable local Change required function from iovalreal_ to iovaldouble_ [needs jgofs_selection_parser 2.5] [needs jgofs_selection_tester 2.5] [needs varnames_in_sel 1.0] [needs parse.h 2.2] [no longer uses parse.c] 10 May 09 v 3.2 WJS Need a version of errn that emulates util's errn 18 Apr 09 v 3.2 WJS Add projections for vars in selections. This may result in reading levels beyond what user asked for, so we need to alter concept of "max level" yet again. Sigh Parametrize attribute delimiters. Fix bug that would have added empty attr lists. Never happened because we always have width= ... but outer doesn't know that. 3 Apr 09 v 3.2 WJS Mods for altered parse (a few funcs were added to parse_functions) Move commented out old parsing code to parse 1 Apr 09 v 3.2 WJS test now returns "Unknown" if the selection vars have not been read in at the time the test is done. Compensate here (This addresses the "not doesn't work" bug) [Needs parse 2.2] [Begin outer 3.2] 14 Feb 09 v 3.1a WJS Change entry points to parse. Reflects precision-dependent mess we got into when we moved the code out of here. Not clear if we are totally out of the woods if inner and outer both use parse and are compiled w/different values of USE_DOUBLE. Present guess: ugly but OK (if basic iovalreal_/iovaldouble_ stuff is OK w/mismatched USE_DOUBLE!) [Begin outer 3.1a] 17 Jan 08 v 3.1 WJS Deal w/possibility that Apache has &/or will change // to / in PATH_ INFOs. This affects both remote object specs and the directory and info server specs (and who knows what else). Try not to confuse // after http: w/ // in remote object & * server specs [Begin outer 3.1] 20 Jul 07 v 3.0b WJS Add &object_info and &method_info in a test mode, turned off by default. NOTE THIS NEW STUFF BREAKS THE jgof_read*.pl methods, which expect &v0 or &c as the first lines. Move parse, test, and the wildcard stuff out of here Change the way outer distinguishes between selections and projections Old code looked for special characters. New code assumes selection if candidate string is not a varname. Among other consequences, a misspelled projection will show up w/a selection error of some kind. However, w/new code, we don't need the list of special characters, and therefore don't need to worry about them being in quotes, etc. [Begin outer 3.0b] 23 Mar 07 v 3.0a WJS Bug fix: out_err had buffer overflow in prepping output message which caused error_ to segv in the free(outname) after it printed the message! Error happened when I indented a portion of the message and forgot to include the indentation chars in the buffer size Change another strcpy to COPY_INTO_FIXED_LEN_BUFFER [Begin outer 3.0a] 26 Oct 06 v 3.0 WJS Bug fix: forgot to remove terminating \n when level removed 20 Oct 06 v 3.0 WJS If a level is totally projected out, remove it from output object Only implemented for non-flat, non-html output. Flat is OK anyway; html has big question regarding to what user-requested level means. Consider a 2 level object whose 2nd level is a 1 level object Consider the object specified by projecting out level 0 of this object. Old behavior was that projected object had 2 levels, 1st of which had nothing in it. New behavior is that projected object has 1 level. A note in case it seems that outer should preserve level structure: outer always truncated max level if it was projected out (eg, 2 level object w/only level 0 vars projected in only output level 0). Therefore, outer never preserved the structure Logically, THIS BREAKS THINGS, not at the code level but at the level of "how many levels in this object?" etc Get get_logical_value from library. Change some strcpy/strcats to library length-checking versions. 8 Sep 06 v 3.0 WJS Move older comments out. Start calling this outer again, instead of outer_brev [Begin outer 3.0] *** End of outer_brev *** 12 Jul 06 v 2.1 WJS BACKGROUND_COLOR; DISPLAY_DATA_URL. Per Bob by request from NEC project Results in adding
& tags even if new stuff isn't spec'd 20 Oct 05 v 2.1 WJS Bug fix: didn't properly handle escaped chars 6 Oct 05 v 2.1 WJS Add "like" string comparison function Add upper-cased version of string comparison functions to do case-blind comparisons parse used to add a $ to selection strings as a non-null to indicate string end. Seems to me that this would conflict if we actually searched for a $, so switch it to something binary (and check input string just in case) [Needs outer.h 1.4] [Begin 2.1] [Comments pre-v2.1 removed to outer_revision.doc. WJS 8 Sep 06] */ /* =========================================== Subroutines required: =========================================== */ int ioopen_(); /* int ioopen_(s,nparams,ntotal) char s[][]; int *nparams,*ntotal; s[0..nparams-1]: parameter strings. Inner sets s[j][0]=0 for any strings which it processes; others will be processed by outer. Thus selection/projections would normally be ignored by inner. nparams: number of parameter strings ntotal (returned): total number of variable names */ int ioreadrec_(); /* int ioreadrec_(level) int *level; Read record at appropriate level. Return 0 if end at that level. Return 1 if ok. */ void ioclose_(); /* ioclose_() Close files Note: this routine should NOT call error_ */ void iovaldouble_(); /* iovaldouble_(vn,df) int *vn; double *df; Return numeric double precision value (df) for variable indexed by vn. -9999. is returned if the datum is not numeric */ void iovalstr_(); /* iovalstr_(vn,tmp) int *vn; char *tmp; Return string value (tmp) for variable indexed by vn. */ int iovarlevel_(); /* int iovarlevel_(vn) int *vn; Return level corresponding to variable indexed by vn. */ int ioattrout_(); /* ioattrout_(vn, str) int *vn; char *str; Output next attribute for variable indexed by vn. 0=none left. */ void ioname_(); /* ioname_(vn,s) int *vn; char *s; Return name (s) corresponding to variable number vn. */ int iowidth_(); /* int iowidth_(vn); int *vn; Return length of variable field indexed by vn. */ int iocommout_(); /* int iocommout_(s) char *s; Return next comment string. 0=none left. -1=next comment contains a URL */ #ifndef HAS_OUTER_INTEREST_ENTRY #define HAS_OUTER_INTEREST_ENTRY FALSE #endif #if HAS_OUTER_INTEREST_ENTRY #define OUTER_COMPILATION_OPTION_INTEREST "compiled to use ioexpress_outer_interest_ entry" int ioexpress_outer_interest_(); /* int ioexpress_outer_interest_(flag) int flag; Use flag (TRUE/FALSE as of v 2.0) to tell inner if we want next record from ioreadrec_ or if we have no more interest in this level Get back indicator (unused; TRUE/FALSE as of v 2.0) if inner can respond to a flag of FALSE by somehow ending its own input */ #else #define OUTER_COMPILATION_OPTION_INTEREST "compiled to ignore any ioexpress_outer_interest_ entry" #endif /* All #includes in outer.h */ #include "outer.h" #ifndef TEST_PROTOCOL_ADDITION #define TEST_PROTOCOL_ADDITION FALSE #endif Logical test_protocol_addition=TEST_PROTOCOL_ADDITION; /* jgofs.a functions... */ Logical get_logical_value(); /* HTDoConnect in turn requires some functions, presently found */ /* jgofs.a. Some are HT*.c modules; a couple are in jdb.c */ /* These functions needed only for testing for gifs, which is turned */ /* off by default. However, can't eliminate these defns based on */ /* compile-time TEST_GIFS, since user can spec tests at run time */ /* (only useful time, if functionality useful at all). */ /* If requiring these functions causes trouble (eg, no jgofs.a), */ /* should unconditionally set test_gifs to false. Suggest testing */ /* it first, and aborting if true (on grounds that somebody appears */ /* to want gifs tested, and we're not about to do it) */ int HTDoConnect(); int HTDoRead(); /* Interface to parse and test (now in jgofs.a library) */ /* Note: actual name of functions have _single or _double appended */ /* per compilation options. Work done in parse.h */ void jgofs_selection_parser(); Logical jgofs_selection_tester(); int varnames_in_sel(); /* Really a fancy call to parse */ /* outer_utils.c functions (in jgofs.a as of ~Apr 04) */ char *htmlescape(); char *trigram(); char *un_trigram(); int ntotal; int minlevel; int maxlevel; int reqlevel; int maxobjectlevel; int *outlevel; int brevflag=0; int htmlflag=0; int flatflag=0; int *level=NULL; int brevstart; int brevcount; int brevend; Logical *anydata; /* PATH_INFO stuff. Functions are in path_info_routines */ char *flat_PATH_INFO,*nextlevel_PATH_INFO,*level0_PATH_INFO; char *no_extURL_PATH_INFO,*full_list_PATH_INFO; char *propagate_brev_no_extURL_PATH_INFO; char *make_PATH_INFO_putenv_string(),*get_jgofs_env_datum(); int get_level(); static char *outnames=NULL; char *parsav; char *QUERY_STRING_no_selections; char *objsav; Logical dirlink,doclink,plotlink,lev0link,levnlink,flatlink; Logical quotenolink,toplinks,otheropts,oo_outer,brev_optimize_inner_calls; Logical flat_width_attr,flat_nonwidth_attrs; Logical test_gifs; Logical display_data_url; char *buttonimagesdir; char *background_color; Logical trailing_buttonimagesdir_slash; /* Format of "server" is node (optionally w/port), followed by cgi */ /* program name. Program name by itself can be used if we know */ /* that node is local. A node spec does not include a leading // */ /* (but we'll strip them off found) */ char *dirserver_w_dir; char *optionserver; char *infoserver_w_obj,*infoserver_extURL; char *dataserver,*localnodeport; char *equality_test; /* Links generate string or numeric test? */ char *attr_delims=ATTR_DELIM; /************************************************************************/ char *outer_return_vers() /* Dummy routine. Exists only to force .h file version string into */ /* this module. Note string must not be global or we'll have con- */ /* flicts if another routine similarly includes the version string */ { static char version[] = OUTER_VERSION"/"FULL_OUTERH_VERSION; return version; } void error_(s1,s2) char *s1,*s2; { char *prefix; if(htmlflag){ printf("%s: %s
");
print_vert_bar (NULL,TRUE);
}
}
if (lev0link) {
if (maxlevel == 0) {
ptr = " - At level 0 - ";
ptr1 = gifs[NOLEVEL0_GIF];
print_vert_bar (ptr1,FALSE);
printf("");
} else {
ptr = "Level 0";
ptr1 = gifs[LEVEL0_GIF];
print_vert_bar (ptr1,FALSE);
/* Level 0 button gets query string w/o selections/projections */
/* I still don't know why it doesn't keep any "original" se- */
/* lections/projections, but we certainly don't want any */
/* "clicked-on" selections. See comments up top for dis- */
/* cussion of preservation of inner's args */
/* QUERY_STRING_no_selections may be \0; has its own ? */
/* if needed */
printf ("",
JGOFS_DATA_CGI_SPEC, level0_PATH_INFO, QUERY_STRING_no_selections);
free(QUERY_STRING_no_selections);
}
tag_toplink(ptr, ptr1);
}
if (levnlink) {
if (maxlevel < maxobjectlevel) {
ptr = next_level;
ptr1 = gifs[LEVELN_GIF];
print_vert_bar (ptr1,FALSE);
printf ("",
JGOFS_DATA_CGI_SPEC, nextlevel_PATH_INFO, parsav);
sprintf(next_level,"Level %d (of %d)",maxlevel+1,maxobjectlevel);
} else {
ptr = " - At last level - ";
ptr1 = gifs[NOLEVELN_GIF];
print_vert_bar (ptr1,FALSE);
printf("");
}
tag_toplink(ptr, ptr1);
}
if (flatlink) {
print_vert_bar (gifs[FLAT_GIF],FALSE);
printf ("",
JGOFS_DATA_CGI_SPEC, flat_PATH_INFO, parsav);
tag_toplink("Flat list", gifs[FLAT_GIF]);
}
/* If we are displaying buttons, " comment, above) */
if (any_buttons_on_line_1 || any_buttons_on_line_2) printf("
" (whatever that is) */
/* I wonder if this should also happen in a NOTOPLINKS environment */
/* (See
");
printf("\n");
printf("\n");
print_comments_html();
/* look at attributes to create array of widths - see ioattrout_ */
for(j=0; j%*s",
JGOFS_DATA_CGI_SPEC, nextlevel_PATH_INFO,
parsav, comma, outnames+j*VARNAMEBUFSIZE, equality_test, ptr,
tmp,
field_width-len_datum+2, " "
);
free (ptr);
}
else printf("%-*s ",field_width,tmp);
}
printf("\n");
return;
}
void print_full_list_link (s)
char *s;
{
#define BREVLINKINDENT 16
printf ("%*s%s\n",BREVLINKINDENT," ",s);
printf ("%*sFull data listing\n",
BREVLINKINDENT, " ", JGOFS_DATA_CGI_SPEC, full_list_PATH_INFO, parsav);
return;
}
Logical outputhtml(firsttime)
Logical firsttime;
{
/* linecount (only for abbreviated listing feature) */
static int linecount;
int i,j;
/* minlevel != maxlevel for first record of each maxlevel file */
/* in a multilevel display */
if (minlevel