1 /*
2  * $Id: collec.i,v 1.1 2005-09-18 22:05:54 dhmunro Exp $
3  * Collect variables through all times in a time history file.
4  */
5 /* Copyright (c) 2005, The Regents of the University of California.
6  * All rights reserved.
7  * This file is part of yorick (http://yorick.sourceforge.net).
8  * Read the accompanying LICENSE file for details.
9  */
10 
collect(f,name)11 func collect(f, name)
12 /* DOCUMENT result= collect(f, name_string)
13      scans through all records of the history file F accumulating the
14      variable NAME_STRING into a single array with one additional
15      index varying from 1 to the number of records.
16 
17      NAME_STRING can be either a simple variable name, or a name
18      followed by up to four simple indices which are either nil, an
19      integer, or an index range with constant limits.  (Note that
20      0 or negative indices count from the end of a dimension.)
21 
22      Examples:
23         collect(f, "xle")        -- collects the variable f.xle
24         collect(f, "tr(2,2:)")   -- collects f.tr(2,2:)
25         collect(f, "akap(2,-1:0,)") -- collects f.akap(2,-1:0,)
26                      (i.e.- akap in the last two values of its
27                             second index)
28 
29    SEE ALSO: get_times
30  */
31 {
32   name= strtok(name, " \t(");
33   var= name(1);
34   name= name(2);
35 
36   /* this is yucky -- need a query function for current record number */
37   n0= where(strmatch(print(f),"Current record"));
38   n= 0;
39   if (numberof(n0)) {
40     n0= n0(1);
41     sread, print(f)(n0), n0,n, format=" Current record is number %ld of %ld";
42   } else {
43     error, "no record structure for file?";
44   }
45 
46   local a,b,c,d,e,name;
47 
48   if (!collect_get(a, name)) {
49     jr, f, 1;
50     rslt= array(get_member(f,var), n);
51     for (i=2 ; i<=n ; i++) {
52       jr, f, i;
53       rslt(.., i)= get_member(f,var);
54     }
55   } else if (!collect_get(b, name)) {
56     jr, f, 1;
57     rslt= array(get_member(f,var)(a), n);
58     for (i=2 ; i<=n ; i++) {
59       jr, f, i;
60       rslt(.., i)= get_member(f,var)(a);
61     }
62   } else if (!collect_get(c, name)) {
63     jr, f, 1;
64     rslt= array(get_member(f,var)(a, b), n);
65     for (i=2 ; i<=n ; i++) {
66       jr, f, i;
67       rslt(.., i)= get_member(f,var)(a, b);
68     }
69   } else if (!collect_get(d, name)) {
70     jr, f, 1;
71     rslt= array(get_member(f,var)(a, b, c), n);
72     for (i=2 ; i<=n ; i++) {
73       jr, f, i;
74       rslt(.., i)= get_member(f,var)(a, b, c);
75     }
76   } else if (!collect_get(e, name)) {
77     jr, f, 1;
78     rslt= array(get_member(f,var)(a, b, c, d), n);
79     for (i=2 ; i<=n ; i++) {
80       jr, f, i;
81       rslt(.., i)= get_member(f,var)(a, b, c, d);
82     }
83   } else {
84     error, "too many (>4) subscripts for collect";
85   }
86 
87   jr, f, n0;
88   return rslt;
89 }
90 
91 func collect_get(&ndx, &name)
92 {
93   if (!name) return 0;
94 
95   argc= *pointer(name);
96   list= where(argc==',' | argc==')');
97   if (numberof(list)) {
98     list= list(1);
99     arg= list>1? strpart(name,1:list-1) : "";
100     name= list<strlen(name)? strpart(name,list+1:0) : string(0);
101   } else {
102     arg= name;
103     name= string(0);
104   }
105 
106   argc= *pointer(arg);
107   list= where(argc==':');
108   n= numberof(list);
109 
110   if (n==0) {
111     ndx= collect_num(arg);
112     return 1;
113 
114   } else {
115     l= list(1);
116     mn= l<2? [] : collect_num(strpart(arg, 1:l-1));
117     if (n==1) m= 1;
118     else m= list(2);
119     mx= l>=strlen(arg)? [] : collect_num(strpart(arg, l+1:m-1));
120     if (n==1) {
121       ndx= collect_rng(mn:mx);
122       return 2;
123     } else if (n==2) {
124       inc= m>=strlen(arg)? [] : collect_num(strpart(arg, m+1:0));
125       ndx= collect_rng(mn:mx:inc);
126       return 3;
127     }
128   }
129 
130   error, "index garbled or too complicated";
131   return 0;
132 }
133 
collect_num(text)134 func collect_num(text)
135 {
136   val= 0;
137   s= string(0);
138   n= sread(format="%ld%[^ \t\n]", text, val, s);
139   if (n==1) return val;
140   if (n==0 && !strtok(text," \t")(1)) return [];
141   error, "index too complicated-- not nil, number, or const range";
142   return string(0);
143 }
144 
collect_rng(x)145 func collect_rng(x) { return x; }
146