Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/matc/src/matc.c
5215 views
1
/*****************************************************************************
2
*
3
* Elmer, A Finite Element Software for Multiphysical Problems
4
*
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library (in file ../LGPL-2.1); if not, write
19
* to the Free Software Foundation, Inc., 51 Franklin Street,
20
* Fifth Floor, Boston, MA 02110-1301 USA
21
*
22
*****************************************************************************/
23
24
/*******************************************************************************
25
*
26
* MATC main module.
27
*
28
*******************************************************************************
29
*
30
* Author: Juha Ruokolainen
31
*
32
* Address: CSC - IT Center for Science Ltd.
33
* Keilaranta 14, P.O. BOX 405
34
* 02101 Espoo, Finland
35
* Tel. +358 0 457 2723
36
* Telefax: +358 0 457 2302
37
* EMail: [email protected]
38
*
39
* Date: 30 May 1996
40
*
41
* Modified by:
42
*
43
* Date of modification:
44
*
45
******************************************************************************/
46
/***********************************************************************
47
|
48
| MATC - Last Edited 9. 8. 1988
49
|
50
***********************************************************************/
51
52
/*======================================================================
53
|Syntax of the manual pages:
54
|
55
|FUNCTION NAME(...) params ...
56
|
57
$ usage of the function and type of the parameters
58
? explain the effects of the function
59
= return value and the type of value if not of type int
60
@ globals effected directly by this routine
61
! current known bugs or limitations
62
& functions called by this function
63
~ these functions may interest you as an alternative function or
64
| because they control this function somehow
65
^=====================================================================*/
66
67
68
/*
69
* $Id: matc.c,v 1.7 2007/06/08 08:12:17 jpr Exp $
70
*
71
* $Log: matc.c,v $
72
* Revision 1.7 2007/06/08 08:12:17 jpr
73
* *** empty log message ***
74
*
75
* Revision 1.6 2006/02/07 10:21:42 jpr
76
* Changed visibility of some variables to local scope.
77
*
78
* Revision 1.5 2006/02/02 06:54:44 jpr
79
* small formatting changes.
80
*
81
* Revision 1.3 2005/08/25 13:44:22 vierinen
82
* windoze stuff
83
*
84
* Revision 1.2 2005/05/27 12:26:20 vierinen
85
* changed header install location
86
*
87
* Revision 1.1.1.1 2005/04/14 13:29:14 vierinen
88
* initial matc automake package
89
*
90
* Revision 1.2 1998/08/01 12:34:48 jpr
91
*
92
* Added Id, started Log.
93
*
94
*
95
*/
96
97
#define MODULE_MATC
98
#include "elmer/matc.h"
99
#include "str.h"
100
#include "../config.h"
101
102
#ifdef DEBUG
103
static FILE *fplog;
104
static int tot;
105
#pragma omp threadprivate (fplog, tot)
106
#endif
107
/*======================================================================
108
? main program, initialize few constants and go for it.
109
^=====================================================================*/
110
void mtc_init( FILE *input_file, FILE *output_file, FILE *error_file )
111
{
112
VARIABLE *ptr;
113
114
char str[256];
115
116
int i; /* i'm getting tired with all these i's */
117
118
static char *evalHelp =
119
{
120
"eval( str )\n\n"
121
"Evaluate content variable. Another form of this command is @str.\n"
122
};
123
124
static char *sourceHelp =
125
{
126
"source( name )\n\n"
127
"Execute commands from file given name.\n"
128
};
129
130
static char *helpHelp =
131
{
132
"help or help(\"symbol\")\n\n"
133
"First form of the command gives list of available commands.\n"
134
"Second form gives help on specific routine.\n"
135
};
136
137
#ifdef _OPENMP
138
/* Allocate listheaders for each thread separately */
139
#pragma omp parallel
140
{
141
/* Do malloc and initialize listheaders */
142
listheaders = (LIST *) malloc(sizeof(LIST)*MAX_HEADERS);
143
/* memory allocations */
144
listheaders[ALLOCATIONS].next = NULL;
145
listheaders[ALLOCATIONS].name = "Allocations";
146
/* global CONSTANTS */
147
listheaders[CONSTANTS].next = NULL;
148
listheaders[CONSTANTS].name = "Constants";
149
/* global VARIABLES */
150
listheaders[VARIABLES].next = NULL;
151
listheaders[VARIABLES].name = "Currently defined VARIABLES";
152
/* internal commands */
153
listheaders[COMMANDS].next = NULL;
154
listheaders[COMMANDS].name = "Builtin Functions";
155
/* user defined functions */
156
listheaders[FUNCTIONS].next = NULL;
157
listheaders[FUNCTIONS].name = "User Functions";
158
}
159
#endif /* _OPENMP */
160
161
#ifdef DEBUG
162
fplog = fopen("matcdbg","w");
163
#endif
164
ALLOC_HEAD = (LIST *)NULL;
165
166
/*
167
* input & output & error streams
168
*/
169
math_in = input_file;
170
math_err = error_file;
171
math_out = output_file;
172
173
mtr_com_init(); /* initialize matrix handling commands */
174
var_com_init(); /* "" VARIABLE "" "" */
175
fnc_com_init(); /* "" function handling commands */
176
fil_com_init(); /* "" file handling commands */
177
gra_com_init(); /* "" graphics commands */
178
str_com_init(); /* "" string handling */
179
180
/*
181
* and few others.
182
*/
183
com_init( "eval" , FALSE, FALSE, com_apply, 1, 1, evalHelp );
184
com_init( "source" , FALSE, FALSE, com_source, 1, 1, sourceHelp );
185
com_init( "help" , FALSE, FALSE, com_help , 0, 1, helpHelp );
186
com_init( "quit" , FALSE, FALSE, com_quit , 0, 0, "quit\n" );
187
com_init( "exit" , FALSE, FALSE, com_quit , 0, 0, "exit\n" );
188
189
/*
190
* these constants will always be there for you.
191
*/
192
ptr = const_new("true", TYPE_DOUBLE, 1, 1);
193
M(ptr,0,0) = 1.0;
194
195
ptr = const_new("false", TYPE_DOUBLE, 1, 1);
196
M(ptr,0,0) = 0.0;
197
198
ptr = const_new("stdin", TYPE_DOUBLE, 1, 1);
199
M(ptr,0,0) = 0;
200
201
ptr = const_new("stdout", TYPE_DOUBLE, 1, 1);
202
M(ptr,0,0) = 1;
203
204
ptr = const_new("stderr", TYPE_DOUBLE, 1, 1);
205
M(ptr,0,0) = 2;
206
207
ptr = const_new("pi", TYPE_DOUBLE, 1, 1);
208
M(ptr,0,0) = 2*acos(0.0);
209
210
#if 0
211
/*
212
* trap INTERRUPT and Floating Point Exception signals
213
*/
214
signal(SIGFPE, sig_trap);
215
216
sprintf( str, "%s/lib/mc.ini", getenv("ELMER_POST_HOME") );
217
218
if ( (math_in = fopen( str, "r" ) ) != (FILE *)NULL)
219
{
220
doread();
221
fclose( math_in );
222
}
223
224
/*
225
* and finally standard input.
226
*/
227
math_in = stdin;
228
229
doread();
230
231
var_free();
232
com_free();
233
fnc_free();
234
const_free();
235
236
mem_free_all();
237
238
#ifdef DEBUG
239
fclose(fplog);
240
#endif
241
#endif
242
243
return; /* done */
244
}
245
246
char * mtc_domath( char *str )
247
{
248
VARIABLE *headsave; /* this should not be here */
249
250
jmp_buf jmp, *savejmp; /* save program context */
251
252
void (*sigfunc)() = (void (*)())signal( SIGINT, sig_trap );
253
254
if ( !str || !*str )
255
{
256
str = (char *)doread();
257
signal( SIGINT, sigfunc );
258
return math_out_str;
259
}
260
261
savejmp = jmpbuf;
262
jmpbuf = &jmp;
263
264
#ifdef DEBUG
265
fprintf( stderr, "got [%s]\n", str );
266
#endif
267
if ( math_out_str ) math_out_str[0] = '\0';
268
math_out_count = 0;
269
270
/*
271
* try it
272
*/
273
if (*str != '\0')
274
{
275
ALLOC_HEAD = (LIST *)NULL;
276
headsave = (VARIABLE *)VAR_HEAD;
277
278
/*
279
* normal return takes branch 1,
280
* error() takes branch 2,
281
* quit() takes branch 3.
282
*/
283
switch (setjmp(*jmpbuf))
284
{
285
case 0:
286
(void)doit( str );
287
longjmp(*jmpbuf, 1);
288
break;
289
290
case 1:
291
break;
292
293
case 2:
294
VAR_HEAD = (LIST *)headsave;
295
break;
296
297
case 3:
298
break;
299
}
300
}
301
302
jmpbuf = savejmp;
303
304
signal( SIGINT, sigfunc );
305
306
return math_out_str;
307
}
308
309
#ifdef _OPENMP
310
/* Data with thread-local storage cannot be reliably accessed across DLL
311
borders. Use an accessor function instead. */
312
LIST * mtc_get_listheaders(void) { return listheaders; }
313
#endif /* _OPENMP */
314
315
char *doread(void)
316
/*======================================================================
317
? doread() is really the main loop of this program. Function reads
318
| it's input as strings and gives them to function doit() for
319
| execution. setjmp() function is used for error recovery.
320
|
321
| Memory allocated during the lifetime of this function is
322
| collected to a list represented by the global VARIABLE
323
| ALLOCLIST *alloc_list. If function error() is called, this
324
| list is used to deallocate memory. Normally (well I certainly
325
| hope so) functions which allocate memory deallocate it themselves.
326
|
327
| Program stays in this function until an end of file -condition
328
| is reached or exit- or quit-commands are given.
329
|
330
@ jmp_buf *jmpbuf, ALLOC_LIST *alloc_list
331
& ALLOCMEM, FREEMEM, setjmp(), longjmp()
332
~ doit(), quit(), error()
333
^=====================================================================*/
334
{
335
VARIABLE *headsave; /* this should not be here */
336
337
jmp_buf jmp, *savejmp; /* save program context */
338
339
char *p, *q; /* buffer for input stream */
340
341
savejmp = jmpbuf;
342
jmpbuf = &jmp;
343
344
if ( math_out_str ) math_out_str[0] = '\0';
345
math_out_count = 0;
346
347
p = q = ALLOCMEM(4096);
348
/*
349
* try it
350
*/
351
while(dogets(p, PMODE_MAIN))
352
{
353
if (*p != '\0')
354
{
355
ALLOC_HEAD = (LIST *)NULL;
356
headsave = (VARIABLE *)VAR_HEAD;
357
358
/*
359
* normal return takes branch 1,
360
* error() takes branch 2,
361
* quit() takes branch 3.
362
*/
363
switch (setjmp(*jmpbuf))
364
{
365
case 0:
366
(void)doit(p);
367
longjmp(*jmpbuf, 1);
368
break;
369
370
case 1:
371
break;
372
373
case 2:
374
VAR_HEAD = (LIST *)headsave;
375
break;
376
377
case 3:
378
goto ret;
379
break;
380
}
381
}
382
}
383
384
ret:
385
386
jmpbuf = savejmp;
387
388
FREEMEM(q);
389
390
return math_out_str;
391
}
392
393
VARIABLE *com_quit(void)
394
/*======================================================================
395
? Quit current doread entry by longjumping back to it (nasty).
396
& longjmp
397
~ doread
398
^=====================================================================*/
399
{
400
longjmp(*jmpbuf, 3);
401
402
return (VARIABLE *)NULL; /* won't be executed (hopefully) */
403
}
404
405
int dogets(char *buff, char *prompt)
406
/*======================================================================
407
? Get line from input stream. If both input & output streams are
408
| connected to terminal, this function gives user one of three
409
| (default) prompts:
410
|
411
| MATC>
412
| - normal prompt (PMODE_MAIN)
413
| ....>
414
| - begin end- block is being defined (PMODE_BLOCK)
415
| ####> (PMODE_CONT)
416
| - user has given a #-sign as a last character of
417
| previous line, this line will be concatenated with it
418
|
419
| If current comment character is found from input stream, the
420
| line after this character is discarded. Likewise if current
421
| system command character is found, the rest of the line is
422
| passed to system()-call.
423
|
424
= line got -> TRUE, EOF -> FALSE
425
! There should be a way to get an echo when reading from file.
426
& fprintf(), isatty(), fileno(), strlen(), fgets(), system()
427
^=====================================================================*/
428
{
429
char *ptr = buff, *p; /* Can't get rid of these. */
430
431
if ( !math_in ) return FALSE;
432
433
/*
434
Try figuring out if input & output streams are
435
terminals, if they both are, give user a prompt.
436
*/
437
if (isatty(fileno(math_in)) && isatty(fileno(math_out)))
438
PrintOut( "%s", prompt );
439
440
/*
441
i'm not in the mood to explain this.
442
*/
443
*ptr++ = ' ';
444
445
/*
446
Go for it.
447
*/
448
while((ptr = fgets(ptr, 256, math_in)) != NULL)
449
{
450
451
ptr[strlen(ptr)-1] = '\0';
452
453
/*
454
* Check if the user wants to continue with this line.
455
*/
456
while(ptr[strlen(ptr)-1] == '\\')
457
{
458
ptr += strlen(ptr) - 1;
459
dogets(ptr, PMODE_CONT);
460
}
461
462
/*
463
* if there is only spaces in this line,
464
* don't bother returning it, instead
465
* let's read afresh, otherwise return.
466
*/
467
p = ptr; while(isspace(*p)) p++;
468
469
if (*p != '\0') /* GOOD EXIT HERE */
470
{
471
#if 0
472
/*
473
* Look for the system character, if found
474
* pass rest of the line to system()-call
475
*/
476
for(p = buff; *p; p++)
477
{
478
switch(*p)
479
{
480
case SYSTEM:
481
system(p + 1);
482
PrintOut("\n");
483
*p = '\0'; p--;
484
break;
485
}
486
}
487
#endif
488
if (*buff != '\0')
489
return TRUE; /* OR IF WE ARE HONEST, IT'S HERE */
490
}
491
492
/*
493
if it's terminal give a prompt.
494
*/
495
if (isatty(fileno(math_in)) && isatty(fileno(math_out)))
496
PrintOut("%s", prompt);
497
}
498
499
return FALSE;
500
}
501
502
503
void com_init(char *word, int flag_pw, int flag_ce, VARIABLE *(*sub)(),
504
int minp, int maxp, char *help_text )
505
/*======================================================================
506
? Adds commands to global command list.
507
|
508
| Parameters:
509
| char *word
510
| - the keyword user gives for this command to be executed.
511
| int flag_pw
512
| - flag telling if the command can be executed element
513
| by element using function *(*sub)().
514
| int flag_ce
515
| - flag telling if the command can be executed when
516
| preprocessing if constant arguments
517
| double *(*sub)()
518
| - function to be executed when this command is given
519
| int minp, maxp
520
| - maximum and minimum number of parameters to command
521
|
522
| The global list of available commands is updated (or created if
523
| nonexistent).
524
|
525
& lst_add()
526
~ *_com_init()
527
^=====================================================================*/
528
{
529
COMMAND *ptr; /* can't get rid of this */
530
531
532
/*
533
Fill the structure...
534
*/
535
ptr = (COMMAND *)ALLOCMEM(COMSIZE);
536
NAME(ptr) = STRCOPY(word);
537
if (flag_pw)
538
ptr->flags |= CMDFLAG_PW;
539
if (flag_ce)
540
ptr->flags |= CMDFLAG_CE;
541
ptr->minp = minp;
542
ptr->maxp = maxp;
543
ptr->sub = sub;
544
ptr->help = help_text;
545
546
/*
547
...and update the list.
548
*/
549
lst_add(COMMANDS, (LIST *)ptr);
550
551
return;
552
}
553
554
void com_free(void)
555
/*======================================================================
556
? Deletes the list of commands and frees associated memory.
557
|
558
& lst_purge()
559
^=====================================================================*/
560
{
561
/*
562
Give memory back to system
563
*/
564
lst_purge(COMMANDS);
565
566
return;
567
}
568
569
COMMAND *com_check(char *str)
570
/*======================================================================
571
? Look for command from COMMANDS list by name.
572
|
573
= COMMAND *NULL if does not exist, pointer to command otherwise
574
& lst_find()
575
^=====================================================================*/
576
{
577
return (COMMAND *)lst_find(COMMANDS, str);
578
}
579
580
VARIABLE *com_help( VARIABLE *ptr )
581
/*======================================================================
582
? Print list of commands and user defined functions from global lists.
583
|
584
! The command to get here is "help" but it really is not very helpful.
585
|
586
& lst_print()
587
^=====================================================================*/
588
{
589
COMMAND *cmd;
590
FUNCTION *fnc;
591
char *name;
592
593
if ( !ptr )
594
{
595
596
lst_print(COMMANDS);
597
lst_print(FUNCTIONS);
598
599
} else {
600
601
name = var_to_string( ptr );
602
603
if ( (cmd = com_check( name ) ) != (COMMAND *)NULL )
604
{
605
606
if ( cmd->help )
607
PrintOut( "\n%s\n", cmd->help );
608
else
609
PrintOut( "\nSorry: no help available on [%s].\n", name );
610
611
} else if ( (fnc = fnc_check( name ) ) != (FUNCTION *)NULL )
612
{
613
614
if ( fnc->help )
615
PrintOut( "\n%s", fnc->help );
616
else
617
PrintOut( "\nSorry: no help available on [%s].\n", name );
618
619
} else {
620
621
error( "help: symbol not found: [%s]\n", name );
622
623
}
624
625
FREEMEM( name );
626
}
627
628
return (VARIABLE *)NULL;
629
}
630
631
VARIABLE *com_pointw(double (*sub)(), VARIABLE *ptr)
632
/*======================================================================
633
? This routine does a function call (*sub)(), for each element in
634
| matrix given by ptr.
635
|
636
= a temporary VARIABLE for which M(res, i, j) = (*sub)(M(ptr, i, j)
637
& var_temp_new(), *(sub)()
638
^=====================================================================*/
639
{
640
VARIABLE *res,*ptr2; /* pointer to result structure */
641
642
double *a, *a2, *a3, *b; /* pointer to matrices */
643
int n, m, sz; /* matrix dimensions */
644
645
int i; /* loop index */
646
647
/*
648
Get space for result and ...
649
*/
650
n = NROW(ptr); m = NCOL(ptr);
651
res = var_temp_new(TYPE(ptr) ,n , m);
652
653
sz = n*m;
654
a = MATR(ptr); b = MATR(res);
655
656
/*
657
...to action.
658
*/
659
ptr2 = NEXT(ptr);
660
if(ptr2)
661
{
662
if(n!=NROW(ptr2)||m!=NCOL(ptr2))
663
{
664
error("Pointwise function arguments must all be of same size.");
665
}
666
a2 = MATR(ptr2);
667
668
ptr2 = NEXT(ptr2);
669
if(ptr2)
670
{
671
if(n!=NROW(ptr2)||m!=NCOL(ptr2))
672
{
673
error("Pointwise function arguments must all be of same size,");
674
}
675
if(NEXT(ptr2))
676
{
677
error("Currently at most three arguments for pointwise functions allowed, sorry.");
678
}
679
a3 = MATR(ptr2);
680
for(i = 0; i < sz; i++)
681
*b++ = ((double (*)(double, double, double)) sub)(*a++, *a2++, *a3++);
682
}
683
else
684
{
685
for(i = 0; i < sz; i++)
686
*b++ = ((double (*)(double, double)) sub)(*a++, *a2++);
687
}
688
}
689
else
690
{
691
for(i = 0; i < sz; i++)
692
*b++ = ((double (*)(double)) sub)(*a++);
693
}
694
695
return res;
696
}
697
698
VARIABLE *com_el(VARIABLE *ptr)
699
/*======================================================================
700
? Extracts specified elements from a matrix. Indexes are given by two
701
| column vectors. The values of the elements of these vectors give
702
| the required indexes. If there is only one index vector given
703
| it is assumed to be column index and row index is set to scalar 0.
704
|
705
| If matrix x is, for example,
706
|
707
| 1 2
708
| 3 4
709
|
710
| you get the first row by
711
|
712
| x[0, 0 1]
713
|
714
| or by
715
|
716
| x(0 1)
717
|
718
= A new temporary VARIABLE, whose size equals to
719
| number of row indexes times number of column indexes.
720
|
721
& var_temp_new(), var_delete_temp()
722
^=====================================================================*/
723
{
724
VARIABLE *res, /* result ... */
725
*par = NEXT(ptr); /* pointer to list of VARIABLES */
726
/* containing indexes */
727
728
static double defind = 0.0;
729
#pragma omp threadprivate (defind)
730
double *ind1 = &defind, *ind2;
731
732
int i, j, k, /* loop indexes */
733
rows, cols, /* no. of rows and columns in the matrix */
734
/* to be indexed. */
735
size1 = 1, size2,
736
ind;
737
738
rows = NROW(ptr); cols = NCOL(ptr);
739
740
/*
741
* check if scalar ....
742
*/
743
if (rows == 1 && cols == 1)
744
{
745
if (*MATR(par) != 0) error("Index out of bounds.\n");
746
if (NEXT(par) != NULL)
747
if (*MATR(NEXT(par)) != 0) error("Index out of bounds.\n");
748
res = var_temp_new(TYPE(ptr),1,1);
749
*MATR(res) = *MATR(ptr);
750
return res;
751
}
752
753
/*
754
The matrix will be indexed by two column vectors.
755
If there is just one assume it's column index and
756
make rowindex 0.
757
*/
758
if (NEXT(par) == NULL)
759
{
760
if (NROW(par) == rows && NCOL(par) == cols)
761
{
762
int logical = TRUE,
763
onecount=0;
764
765
double *dtmp;
766
767
dtmp = MATR(par);
768
for(i = 0; i < NROW(par)*NCOL(par); i++)
769
if (dtmp[i] == 0)
770
{
771
}
772
else if (dtmp[i] == 1)
773
{
774
onecount++;
775
}
776
else
777
{
778
logical = FALSE;
779
break;
780
}
781
782
if (logical)
783
{
784
if (onecount == 0) return NULL;
785
786
res = var_temp_new(TYPE(ptr),1,onecount);
787
for(i=0,k=0; i < rows; i++)
788
for(j=0; j < cols; j++)
789
if (M(par,i,j) == 1)
790
{
791
memcpy(&M(res,0,k++),&M(ptr,i,j),sizeof(double));
792
}
793
return res;
794
}
795
}
796
797
ind2 = MATR(par); size2 = NCOL(par);
798
cols *= rows; rows = 1;
799
}
800
else
801
{
802
ind1 = MATR(par); size1 = NCOL(par);
803
size2 = NCOL(NEXT(par));
804
ind2 = MATR(NEXT(par));
805
}
806
807
/*
808
Space for result
809
*/
810
res = var_temp_new(TYPE(ptr), size1, size2);
811
812
/*
813
Extract the values (try making sense out of that
814
if you feel like it).
815
*/
816
for(i = 0; i < size1; i++)
817
{
818
ind = (int)ind1[i];
819
for(j = 0; j < size2; j++)
820
if (ind < rows && (int)ind2[j] < cols)
821
memcpy(&M(res,i,j),&M(ptr,ind,(int)ind2[j]),sizeof(double));
822
else
823
error("Index out of bounds.\n");
824
}
825
826
return res;
827
}
828
829
VARIABLE *com_source(VARIABLE *ptr)
830
/*======================================================================
831
? Redirect input stream to a file, whose name is given.
832
|
833
@ FILE *math_in
834
& ALLOCMEM, FREEMEM, fopen(), fclose(), error()
835
^=====================================================================*/
836
{
837
char *name; /* Hold converted string (file name) */
838
839
FILE *save_in = math_in; /* Save previous input stream until */
840
/* we are done with the new file. */
841
842
/*
843
convert the file name from ptr.
844
*/
845
name = var_to_string(ptr);
846
847
/*
848
Execute the file.
849
*/
850
if ((math_in = fopen(name,"r")) != NULL)
851
{
852
/* PrintOut("Executing commands from file, %s...\n", name); */
853
doread();
854
fclose(math_in);
855
}
856
else
857
{
858
PrintOut( "Source: Can't open file, %s.\n",name );
859
}
860
861
math_in = save_in;
862
FREEMEM(name);
863
864
return (VARIABLE *)NULL;
865
}
866
867
868
VARIABLE *com_apply(VARIABLE *ptr)
869
/*======================================================================
870
? Executes given string.
871
|
872
& ALLOCMEM, FREEMEM, doit()
873
^=====================================================================*/
874
{
875
VARIABLE *res; /* result pointer */
876
877
char *p, *q; /* holds the string to be executed, after */
878
/* conversion from structure VARIABLE * */
879
880
int i, j; /* just loop indexes */
881
882
883
/*
884
Allocate space for the string...
885
*/
886
p = q = ALLOCMEM(NROW(ptr) * NCOL(ptr) + 1);
887
888
/*
889
... convert it ...
890
*/
891
for(i = 0; i < NROW(ptr); i++)
892
for(j = 0; j < NCOL(ptr); j++)
893
*p++ = (char)M(ptr,i,j);
894
895
*p = '\0';
896
897
/*
898
... and try executing it.
899
*/
900
res = doit( q );
901
902
FREEMEM(q);
903
904
return res;
905
}
906
907
void mem_free(void *mem)
908
/*======================================================================
909
? Free memory given by argument, and unlink it from allocation list.
910
| Currently FREEMEM(ptr) is defined to be mem_free(ptr).
911
|
912
& free()
913
~ mem_alloc(), mem_free_all()
914
^=====================================================================*/
915
{
916
ALLOC_LIST *lst;
917
918
#ifdef DEBUG
919
tot--; fprintf(fplog,"free addr: %d total: %d\n", ALLOC_LST(mem), tot);
920
fflush( fplog );
921
#endif
922
/*
923
if the list is empty return
924
*/
925
if ( (lst = (ALLOC_LIST *)ALLOC_HEAD) == (ALLOC_LIST *)NULL )
926
{
927
#if 1
928
/* ????? */
929
free( ALLOC_LST(mem) );
930
#else
931
fprintf( stderr, "SHOULD THIS HAPPEN ????\n" );
932
#endif
933
return;
934
}
935
936
/*
937
* it's not the header, look if it's in list at all
938
*/
939
if (ALLOC_PTR(lst) != mem)
940
{
941
942
for(; NEXT(lst); lst = NEXT(lst))
943
{
944
if (ALLOC_PTR(NEXT(lst)) == mem) break;
945
}
946
947
/*
948
* item was not found from the list. free ptr and return.
949
*/
950
if (NEXT(lst) == (ALLOC_LIST *)NULL)
951
{
952
free(ALLOC_LST(mem));
953
return;
954
}
955
956
/*
957
* unlink
958
*/
959
NEXT(lst) = NEXT(NEXT(lst));
960
}
961
962
/*
963
* item was the header, unlink it
964
*/
965
else
966
ALLOC_HEAD = NEXT(ALLOC_HEAD);
967
968
/*
969
* and at last return memory back to system
970
*/
971
free(ALLOC_LST(mem));
972
973
return;
974
}
975
976
void mem_free_all(void)
977
/*======================================================================
978
? Free all memory allocated since last entry of doread.
979
| (actually free all memory from list ALLOCATIONS).
980
|
981
~ mem_alloc(), mem_free(), doread(), error()
982
^=====================================================================*/
983
{
984
ALLOC_LIST *lst, *lstn;
985
986
for(lst = (ALLOC_LIST *)ALLOC_HEAD; lst;)
987
{
988
#ifdef DEBUG
989
tot--; fprintf(fplog,"freeall addr: %d total: %d\n", lst, tot);
990
fflush( fplog );
991
#endif
992
lstn = NEXT(lst);
993
free( (char *)lst );
994
lst = lstn;
995
}
996
997
ALLOC_HEAD = (LIST *)NULL; /* security */
998
999
return;
1000
}
1001
1002
void *mem_alloc(size_t size)
1003
/*======================================================================
1004
? Allocate memory and link it to memory allocation list.
1005
|
1006
~ calloc(), free(), error()
1007
^=====================================================================*/
1008
{
1009
ALLOC_LIST *lst;
1010
1011
/*
1012
* try allocating memory
1013
*/
1014
if ((lst = (ALLOC_LIST *)calloc(size+sizeof(ALLOC_LIST), 1)) != NULL)
1015
{
1016
NEXT(lst) = (ALLOC_LIST *)ALLOC_HEAD; ALLOC_HEAD = (LIST *)lst;
1017
}
1018
else
1019
error("Can't alloc mem.\n");
1020
1021
#ifdef DEBUG
1022
tot++; fprintf(fplog,"alloc addr: %d size: %d total: %d\n",
1023
lst, size, tot);
1024
fflush( fplog );
1025
#endif
1026
return ALLOC_PTR(lst);
1027
}
1028
1029