ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.5
Committed: Mon Jun 30 14:59:13 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.4: +6 -3 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.3 static const char RCSid[] = "$Id";
3 greg 3.1 #endif
4     /*
5     * Radiance object animation program
6     *
7     * Main program and control file handling.
8     *
9     * See ranimove.h and the ranimove(1) man page for details.
10     */
11    
12 greg 3.2 #include "copyright.h"
13 greg 3.1
14 greg 3.3 #include <time.h>
15 schorsch 3.4 #ifndef _WIN32
16     #include <sys/time.h>
17     #endif
18 greg 3.1 #include <ctype.h>
19 schorsch 3.5 #include <string.h>
20    
21     #include "paths.h"
22     #include "ranimove.h"
23 greg 3.1
24     int NVARS = NV_INIT; /* total number of variables */
25    
26     VARIABLE vv[] = VV_INIT; /* variable-value pairs */
27    
28     extern int nowarn; /* don't report warnings? */
29     int silent = 0; /* run silently? */
30    
31     int quickstart = 0; /* time initial frame as well? */
32    
33     int nprocs = 1; /* number of rendering processes */
34    
35     int rtperfrm = 60; /* seconds to spend per frame */
36    
37     double ndthresh = 2.; /* noticeable difference threshold */
38     int ndtset = 0; /* user threshold -- stop when reached? */
39    
40     int fbeg = 1; /* starting frame */
41     int fend = 0; /* ending frame */
42     int fcur; /* current frame being rendered */
43    
44     char lorendoptf[32]; /* low quality options file */
45     RAYPARAMS lorendparams; /* low quality rendering parameters */
46     char hirendoptf[32]; /* high quality options file */
47     RAYPARAMS hirendparams; /* high quality rendering parameters */
48     RAYPARAMS *curparams; /* current parameter settings */
49     int twolevels; /* low and high quality differ */
50    
51     double mblur; /* vflt(MBLUR) */
52     double rate; /* vflt(RATE) */
53    
54     char objtmpf[32]; /* object temporary file */
55    
56     struct ObjMove *obj_move; /* object movements */
57    
58     int haveprio = 0; /* high-level saliency specified */
59    
60     int gargc; /* global argc for printargs */
61     char **gargv; /* global argv for printargs */
62    
63    
64     int
65     main(argc, argv)
66     int argc;
67     char *argv[];
68     {
69     int explicate = 0;
70     char *cfname;
71     int i;
72    
73     progname = argv[0]; /* get arguments */
74     gargc = argc;
75     gargv = argv;
76     for (i = 1; i < argc && argv[i][0] == '-'; i++)
77     switch (argv[i][1]) {
78     case 't': /* seconds per frame */
79     rtperfrm = atoi(argv[++i]);
80     break;
81     case 'd': /* noticeable difference */
82     ndthresh = atof(argv[++i]);
83     ndtset = 1;
84     break;
85     case 'e': /* print variables */
86     explicate++;
87     break;
88     case 's': /* silent running */
89     silent++;
90     break;
91     case 'q': /* start quickly */
92     quickstart++;
93     break;
94     case 'w': /* turn off warnings */
95     nowarn++;
96     break;
97     case 'f': /* frame range */
98     switch (sscanf(argv[++i], "%d,%d", &fbeg, &fend)) {
99     case 2:
100     if ((fbeg <= 0 | fend < fbeg))
101     goto userr;
102     break;
103     case 1:
104     if (fbeg <= 0)
105     goto userr;
106     fend = 0;
107     break;
108     default:
109     goto userr;
110     }
111     break;
112     case 'n': /* number of processes */
113     nprocs = atoi(argv[++i]);
114     break;
115     default:
116     goto userr;
117     }
118     if (rtperfrm <= 0) {
119     if (!ndtset)
120     error(USER, "specify -d jnd with -t 0");
121     rtperfrm = 7*24*3600;
122     }
123     if (i != argc-1)
124     goto userr;
125     cfname = argv[i];
126     /* load variables */
127     loadvars(cfname);
128     /* check variables */
129     checkvalues();
130     /* load RIF if any */
131     if (vdef(RIF))
132     getradfile(vval(RIF));
133     /* set defaults */
134     setdefaults();
135     /* print variables */
136     if (explicate)
137     printvars(stdout);
138     /* run animation */
139     if (nprocs > 0)
140     animate();
141     /* all done */
142     if (lorendoptf[0])
143     unlink(lorendoptf);
144     if (hirendoptf[0])
145     unlink(hirendoptf);
146     if (objtmpf[0])
147     unlink(objtmpf);
148     return(0);
149     userr:
150     fprintf(stderr,
151     "Usage: %s [-n nprocs][-f beg,end][-t sec][-d jnd][-s][-w][-e] anim_file\n",
152     progname);
153     quit(1);
154     }
155    
156    
157     void
158     eputs(s) /* put string to stderr */
159     register char *s;
160     {
161     static int midline = 0;
162    
163     if (!*s)
164     return;
165     if (!midline++) {
166     fputs(progname, stderr);
167     fputs(": ", stderr);
168     }
169     fputs(s, stderr);
170     if (s[strlen(s)-1] == '\n') {
171     fflush(stderr);
172     midline = 0;
173     }
174     }
175    
176    
177     void
178     setdefaults() /* set default values */
179     {
180     int nviews;
181     int decades;
182     char buf[256];
183     int i;
184    
185     if (!vdef(OCTREEF)) {
186     sprintf(errmsg, "%s or %s must be defined",
187     vnam(OCTREEF), vnam(RIF));
188     error(USER, errmsg);
189     }
190     if (!vdef(VIEWFILE)) {
191     sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
192     error(USER, errmsg);
193     }
194     nviews = countviews();
195     if (!nviews)
196     error(USER, "no views in view file");
197     if (!vdef(END)) {
198     if (nviews == 1) {
199     sprintf(errmsg, "%s must be defined for single view",
200     vnam(END));
201     error(USER, errmsg);
202     }
203     sprintf(buf, "%d", nviews);
204     vval(END) = savqstr(buf);
205     vdef(END)++;
206     }
207     if (!fend)
208     fend = vint(END);
209     if (fbeg > fend)
210     error(USER, "begin after end");
211     if (!vdef(BASENAME)) {
212     decades = (int)log10((double)vint(END)) + 1;
213     if (decades < 3) decades = 3;
214     sprintf(buf, "frame%%0%dd", decades);
215     vval(BASENAME) = savqstr(buf);
216     vdef(BASENAME)++;
217     }
218     if (!vdef(RATE)) {
219     vval(RATE) = "8";
220     vdef(RATE)++;
221     }
222     rate = vflt(RATE);
223     if (!vdef(RESOLUTION)) {
224     vval(RESOLUTION) = "640";
225     vdef(RESOLUTION)++;
226     }
227     if (!vdef(MBLUR)) {
228     vval(MBLUR) = "0";
229     vdef(MBLUR)++;
230     }
231     mblur = vflt(MBLUR);
232     if (mblur > 1.)
233     mblur = 1.;
234     /* set up objects */
235     if (vdef(MOVE)) {
236     obj_move = (struct ObjMove *)malloc(
237     sizeof(struct ObjMove)*vdef(MOVE) );
238     if (obj_move == NULL)
239     error(SYSTEM, "out of memory in setdefaults");
240     for (i = 0; i < vdef(MOVE); i++)
241     setmove(&obj_move[i], nvalue(MOVE, i));
242     }
243     /* set up high quality options */
244     setrendparams(hirendoptf, vval(HIGHQ));
245     ray_save(&hirendparams);
246     /* set up low quality options */
247     setrendparams(lorendoptf, vval(LOWQ));
248     ray_save(&lorendparams);
249     curparams = &lorendparams;
250 schorsch 3.5 twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
251 greg 3.1 }
252    
253    
254     void
255     setmove(om, ms) /* assign a move object from spec. */
256     struct ObjMove *om;
257     char *ms;
258     {
259     char parname[128];
260     char *cp;
261    
262     ms = nextword(parname, sizeof(parname), ms);
263     if (!parname[0])
264     goto badspec;
265     for (cp = parname; *cp; cp++)
266     if (isspace(*cp))
267     *cp = '_';
268     for (om->parent = (om - obj_move); om->parent--; )
269     if (!strcmp(parname, obj_move[om->parent].name))
270     break;
271     if (om->parent < 0 &&
272     strcmp(parname, ".") && strcmp(parname, VOIDID)) {
273     sprintf(errmsg, "undefined parent object '%s'", parname);
274     error(USER, errmsg);
275     }
276     ms = nextword(om->name, sizeof(om->name), ms);
277     if (!om->name[0])
278     goto badspec;
279     for (cp = om->name; *cp; cp++)
280     if (isspace(*cp))
281     *cp = '_';
282     ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
283     if (!strcmp(om->xf_file, "."))
284     om->xf_file[0] = '\0';
285     if (!om->xf_file[0]) {
286     om->xfs[0] = '\0';
287     } else if (om->xf_file[0] == '-') {
288     strcpy(om->xfs, om->xf_file);
289     om->xf_file[0] = '\0';
290     }
291     ms = nextword(om->spec, sizeof(om->spec), ms);
292     if (om->spec[0]) {
293     if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
294     om->spec[0] = '\0';
295     ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
296     } else
297     om->prio_file[0] = '\0';
298     if (om->prio_file[0]) {
299     if (isflt(om->prio_file)) {
300     om->prio = atof(om->prio_file);
301     om->prio_file[0] = '\0';
302     haveprio |= (om->prio < 0.95 | om->prio > 1.05);
303     } else
304     haveprio = 1;
305     } else
306     om->prio = 1.;
307     om->cfm = -1;
308     return;
309     badspec:
310     error(USER, "bad object specification");
311     }
312    
313    
314     void
315     setrendparams(optf, qval) /* set global rendering parameters */
316     char *optf;
317     char *qval;
318     {
319     char *argv[1024];
320     char **av = argv;
321     int ac, i, rval;
322    
323     av[ac=0] = NULL;
324     /* load options from file, first */
325     if (optf != NULL && *optf) {
326     ac = wordfile(av, optf);
327     if (ac < 0) {
328     sprintf(errmsg, "cannot load options file \"%s\"",
329     optf);
330     error(SYSTEM, errmsg);
331     }
332     }
333     /* then from options string */
334     if (qval != NULL && qval[0] == '-')
335     ac += wordstring(av+ac, qval);
336    
337     /* start with default parameters */
338     ray_defaults(NULL);
339     /* set what we have */
340     for (i = 0; i < ac; i++) {
341     while ((rval = expandarg(&ac, &av, i)) > 0)
342     ;
343     if (rval < 0) {
344     sprintf(errmsg, "cannot expand '%s'", av[i]);
345     error(SYSTEM, errmsg);
346     }
347     if (!strcmp(av[i], "-w")) {
348     nowarn++;
349     continue;
350     }
351     rval = getrenderopt(ac-i, av+i);
352     if (rval >= 0) {
353     i += rval;
354     continue;
355     }
356     sprintf(errmsg, "bad render option at '%s'", av[i]);
357     error(USER, errmsg);
358     }
359     }
360    
361    
362     void
363     getradfile(rfargs) /* run rad and get needed variables */
364     char *rfargs;
365     {
366     static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
367     char combuf[256];
368     register int i;
369     register char *cp;
370     char *pippt;
371     /* create rad command */
372     strcpy(lorendoptf, "ranim0.opt");
373     sprintf(combuf,
374     "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
375     rfargs,
376     (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
377     lorendoptf);
378     cp = combuf;
379     while (*cp) {
380     if (*cp == '|') pippt = cp;
381     cp++;
382     } /* match unset variables */
383     for (i = 0; mvar[i] >= 0; i++)
384     if (!vdef(mvar[i])) {
385     *cp++ = '|';
386     strcpy(cp, vnam(mvar[i]));
387     while (*cp) cp++;
388     pippt = NULL;
389     }
390     if (pippt != NULL)
391 schorsch 3.5 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
392 greg 3.1 else {
393     strcpy(cp, ")[ \t]*=' > ranimove.var");
394     cp += 11; /* point to file name */
395     }
396     system(combuf); /* ignore exit code */
397     if (pippt == NULL) { /* load variables and remove file */
398     loadvars(cp);
399     unlink(cp);
400     }
401     if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
402     strcpy(hirendoptf, lorendoptf);
403     return;
404     }
405     /* get high quality options */
406     strcpy(hirendoptf, "ranim1.opt");
407     sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
408     rfargs, vval(HIGHQ), hirendoptf);
409     system(combuf);
410     }
411    
412    
413     void
414     animate() /* run through animation */
415     {
416     int rpass;
417    
418     if (fbeg > 1) /* synchronize transforms */
419     getoctspec(fbeg-1);
420    
421     for (fcur = fbeg; fcur <= fend; fcur++) {
422     if (!silent)
423     printf("Frame %d:\n", fcur);
424     /* base rendering */
425     init_frame();
426     /* refinement */
427     for (rpass = 0; refine_frame(rpass); rpass++)
428     ;
429     /* final filter pass */
430     filter_frame();
431     /* output frame */
432     send_frame();
433     }
434     /* free resources */
435     free_frame();
436     if (nprocs > 1)
437     ray_pdone(1);
438     else
439     ray_done(1);
440     getview(0);
441     getexp(0);
442     }
443    
444    
445     VIEW *
446     getview(n) /* get view number n */
447     int n;
448     {
449     static FILE *viewfp = NULL; /* view file pointer */
450     static int viewnum = 0; /* current view number */
451     static VIEW curview = STDVIEW; /* current view */
452     char linebuf[256];
453    
454     if (n == 0) { /* signal to close file and clean up */
455     if (viewfp != NULL) {
456     fclose(viewfp);
457     viewfp = NULL;
458     viewnum = 0;
459     copystruct(&curview, &stdview);
460     }
461     return(NULL);
462     }
463     if (viewfp == NULL) { /* open file */
464     if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
465     perror(vval(VIEWFILE));
466     quit(1);
467     }
468     } else if (n > 0 && n < viewnum) { /* rewind file */
469     if (viewnum == 1 && feof(viewfp))
470     return(&curview); /* just one view */
471     if (fseek(viewfp, 0L, 0) == EOF) {
472     perror(vval(VIEWFILE));
473     quit(1);
474     }
475     copystruct(&curview, &stdview);
476     viewnum = 0;
477     }
478     if (n < 0) { /* get next view */
479     register int c = getc(viewfp);
480     if (c == EOF)
481     return(NULL); /* that's it */
482     ungetc(c, viewfp);
483     n = viewnum + 1;
484     }
485     while (n > viewnum) { /* scan to desired view */
486     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
487     return(viewnum==1 ? &curview : (VIEW *)NULL);
488     if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
489     viewnum++;
490     }
491     return(&curview); /* return it */
492     }
493    
494    
495     int
496     countviews() /* count views in view file */
497     {
498     int n;
499    
500     if (getview(n=1) == NULL)
501     return(0);
502     while (getview(-1) != NULL)
503     n++;
504     return(n);
505     }
506    
507    
508     char *
509     getexp(n) /* get exposure for nth frame */
510     int n;
511     {
512     extern char *fskip();
513     static char expval[32];
514     static FILE *expfp = NULL;
515     static int curfrm = 0;
516     register char *cp;
517    
518     if (n == 0) { /* signal to close file */
519     if (expfp != NULL) {
520     fclose(expfp);
521     expfp = NULL;
522     }
523     return(NULL);
524     }
525     if (!vdef(EXPOSURE)) /* no setting (auto) */
526     return(NULL);
527     if (isflt(vval(EXPOSURE))) /* always the same */
528     return(vval(EXPOSURE));
529     if (expfp == NULL) { /* open exposure file */
530     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
531     sprintf(errmsg, "cannot open exposure file \"%s\"",
532     vval(EXPOSURE));
533     error(SYSTEM, errmsg);
534     }
535     curfrm = 0;
536     }
537     if (curfrm > n) { /* rewind if necessary */
538     rewind(expfp);
539     curfrm = 0;
540     }
541     while (n > curfrm) { /* read to line */
542     if (fgets(expval, sizeof(expval), expfp) == NULL) {
543     sprintf(errmsg, "%s: too few exposures",
544     vval(EXPOSURE));
545     error(USER, errmsg);
546     }
547     if (strlen(expval) == sizeof(expval)-1)
548     goto formerr;
549     curfrm++;
550     }
551     cp = fskip(expval); /* check format */
552     if (cp != NULL)
553     while (isspace(*cp))
554     *cp++ = '\0';
555     if (cp == NULL || *cp)
556     goto formerr;
557     return(expval); /* return value */
558     formerr:
559     sprintf(errmsg, "%s: exposure format error on line %d",
560     vval(EXPOSURE), curfrm);
561     error(USER, errmsg);
562     }
563    
564    
565     double
566     expspec_val(s) /* get exposure value from spec. */
567     char *s;
568     {
569     double expval;
570    
571     if (s == NULL || !*s)
572     return(1.0);
573    
574     expval = atof(s);
575     if ((s[0] == '+' | s[0] == '-'))
576     return(pow(2.0, expval));
577     return(expval);
578     }
579    
580    
581     char *
582     getoctspec(n) /* get octree for the given frame */
583     int n;
584     {
585     static char combuf[1024];
586     int cfm = 0;
587     int uses_inline;
588     FILE *fp;
589     int i;
590     /* is octree static? */
591     if (!vdef(MOVE))
592     return(vval(OCTREEF));
593     /* done already */
594     if (n == cfm)
595     return(combuf);
596     /* else create object file */
597     strcpy(objtmpf, "movinobj.rad");
598     fp = fopen(objtmpf, "w");
599     if (fp == NULL) {
600     sprintf(errmsg, "cannot write to moving objects file '%s'",
601     objtmpf);
602     error(SYSTEM, errmsg);
603     }
604     uses_inline = 0;
605     for (i = 0; i < vdef(MOVE); i++) {
606     int inlc = (obj_move[i].spec[0] == '!');
607     if (!obj_move[i].spec[0])
608     continue;
609     if (inlc)
610     fprintf(fp, "%s %d \\\n\t| xform",
611     obj_move[i].spec, n);
612     else
613     fputs("!xform", fp);
614     fprintf(fp, " -n %s", getobjname(&obj_move[i]));
615     fputs(getxf(&obj_move[i], n), fp);
616     if (!inlc)
617     fprintf(fp, " %s\n", obj_move[i].spec);
618     else
619     fputc('\n', fp);
620     uses_inline |= inlc;
621     }
622     if (fclose(fp) == EOF)
623     error(SYSTEM, "error writing moving objects file");
624     if (uses_inline)
625     sprintf(combuf, "!oconv %s -f -i '%s' %s",
626     vdef(OCONV) ? vval(OCONV) : "",
627     vval(OCTREEF), objtmpf);
628     else
629     sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
630     objtmpf, vval(OCTREEF));
631     return(combuf);
632     }
633    
634    
635     char *
636     getobjname(om) /* get fully qualified object name */
637     register struct ObjMove *om;
638     {
639     static char objName[512];
640     register char *cp = objName;
641    
642     strcpy(cp, om->name);
643     while (om->parent >= 0) {
644     while (*cp) cp++;
645     *cp++ = '@';
646     om = &obj_move[om->parent];
647     strcpy(cp, om->name);
648     }
649     return(objName);
650     }
651    
652    
653     char *
654     getxf(om, n) /* get total transform for object */
655     register struct ObjMove *om;
656     int n;
657     {
658     static char xfsbuf[4096];
659     char *xfp;
660     int framestep = 0;
661     XF oxf;
662     FILE *fp;
663     char abuf[512];
664     char *av[64];
665     int ac;
666     int i;
667     register char *cp;
668     /* get parent transform, first */
669     if (om->parent >= 0)
670     xfp = getxf(&obj_move[om->parent], n);
671     else
672     *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
673     /* get transform spec. & priority */
674     if (om->cfm != n) {
675     if (om->xf_file[0]) {
676     fp = fopen(om->xf_file, "r");
677     if (fp == NULL) {
678     sprintf(errmsg,
679     "cannot open transform file '%s'",
680     om->xf_file);
681     error(SYSTEM, errmsg);
682     }
683     for (i = 0; i < n; i++)
684     if (fgetline(om->xfs, sizeof(om->xfs), fp)
685     == NULL) {
686     sprintf(errmsg,
687     "too few transforms in file '%s'",
688     om->xf_file);
689     error(USER, errmsg);
690     }
691     fclose(fp);
692     }
693     strcpy(cp=abuf, om->xfs);
694     ac = 0;
695     for ( ; ; ) {
696     while (isspace(*cp))
697     *cp++ = '\0';
698     if (!*cp)
699     break;
700     av[ac++] = cp;
701     while (*++cp && !isspace(*cp))
702     ;
703     }
704     av[ac] = NULL;
705     if (xf(&oxf, ac, av) != ac ||
706     fabs(oxf.sca) <= FTINY) {
707     sprintf(errmsg, "bad transform args: %s",
708     om->xfs);
709     error(USER, errmsg);
710     }
711     copymat4(om->xfm, oxf.xfm);
712     if (om->prio_file[0]) {
713     fp = fopen(om->prio_file, "r");
714     if (fp == NULL) {
715     sprintf(errmsg,
716     "cannot open priority file '%s'",
717     om->prio_file);
718     error(SYSTEM, errmsg);
719     }
720     for (i = 0; i < n; i++)
721     if (fgets(abuf, sizeof(abuf), fp)
722     == NULL) {
723     sprintf(errmsg,
724     "too few priorities in file '%s'",
725     om->prio_file);
726     error(USER, errmsg);
727     }
728     fclose(fp);
729     cp = fskip(abuf);
730     if (cp != NULL)
731     while (isspace(*cp))
732     *cp++ = '\0';
733     if (cp == NULL || *cp) {
734     sprintf(errmsg,
735     "priority '%s' in file '%s' not a number",
736     abuf, om->prio_file);
737     error(USER, errmsg);
738     }
739     om->prio = atof(abuf);
740     }
741     framestep = (n == om->cfm + 1);
742     om->cfm = n;
743     }
744     /* prepend to parent transform */
745     if (om->xfs[0]) {
746     i = strlen(om->xfs);
747     if (xfp - i <= xfsbuf)
748     error(INTERNAL, "transform too long in getxf");
749     cp = om->xfs + i;
750     while (i--)
751     *--xfp = *--cp;
752     *--xfp = ' ';
753     }
754     if (framestep)
755     copymat4(oxf.xfm, om->cxfm);
756     if (om->parent >= 0) {
757     multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
758     om->cprio = obj_move[om->parent].cprio * om->prio;
759     } else {
760     copymat4(om->cxfm, om->xfm);
761     om->cprio = om->prio;
762     }
763     /* XXX bxfm relies on call order */
764     if (framestep)
765     if (invmat4(om->bxfm, om->cxfm))
766     multmat4(om->bxfm, om->bxfm, oxf.xfm);
767     else
768     setident4(om->bxfm);
769     /* all done */
770     return(xfp);
771     }
772    
773    
774     int
775     getmove(obj) /* find matching move object */
776     OBJECT obj;
777     {
778     static int lasti;
779     static OBJECT lasto = OVOID;
780     char *onm, *objnm;
781     int len, len2;
782     register int i;
783    
784     if (obj == OVOID)
785     return(-1);
786     if (obj == lasto)
787     return(lasti);
788     /* look for matching object */
789     onm = objptr(obj)->oname;
790     for (i = vdef(MOVE); i--; ) {
791     objnm = obj_move[i].name;
792     len = strlen(objnm);
793     if (!strncmp(onm, objnm, len)) {
794     if ((obj_move[i].parent < 0 & onm[len] == '.'))
795     break;
796     objnm = getobjname(&obj_move[i]) + len;
797     len2 = strlen(objnm);
798     if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
799     break;
800     }
801     }
802     lasto = obj; /* cache what we found */
803     return(lasti = i);
804     }
805    
806    
807     double
808     obj_prio(obj) /* return priority for object */
809     OBJECT obj;
810     {
811     int moi;
812    
813     if (obj == OVOID || (moi = getmove(obj)) < 0)
814     return(1.0);
815     return(obj_move[moi].cprio);
816     }
817    
818    
819     double
820     getTime() /* get current time (CPU or real) */
821     {
822     struct timeval time_now;
823     /* return CPU time if one process */
824     if (nprocs == 1)
825     return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
826     /* otherwise, return wall time */
827     gettimeofday(&time_now, NULL);
828     return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
829     }