Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/matc/src/matc.c
3196 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
char *doread(void)
310
/*======================================================================
311
? doread() is really the main loop of this program. Function reads
312
| it's input as strings and gives them to function doit() for
313
| execution. setjmp() function is used for error recovery.
314
|
315
| Memory allocated during the lifetime of this function is
316
| collected to a list represented by the global VARIABLE
317
| ALLOCLIST *alloc_list. If function error() is called, this
318
| list is used to deallocate memory. Normally (well I certainly
319
| hope so) functions which allocate memory deallocate it themselves.
320
|
321
| Program stays in this function until an end of file -condition
322
| is reached or exit- or quit-commands are given.
323
|
324
@ jmp_buf *jmpbuf, ALLOC_LIST *alloc_list
325
& ALLOCMEM, FREEMEM, setjmp(), longjmp()
326
~ doit(), quit(), error()
327
^=====================================================================*/
328
{
329
VARIABLE *headsave; /* this should not be here */
330
331
jmp_buf jmp, *savejmp; /* save program context */
332
333
char *p, *q; /* buffer for input stream */
334
335
savejmp = jmpbuf;
336
jmpbuf = &jmp;
337
338
if ( math_out_str ) math_out_str[0] = '\0';
339
math_out_count = 0;
340
341
p = q = ALLOCMEM(4096);
342
/*
343
* try it
344
*/
345
while(dogets(p, PMODE_MAIN))
346
{
347
if (*p != '\0')
348
{
349
ALLOC_HEAD = (LIST *)NULL;
350
headsave = (VARIABLE *)VAR_HEAD;
351
352
/*
353
* normal return takes branch 1,
354
* error() takes branch 2,
355
* quit() takes branch 3.
356
*/
357
switch (setjmp(*jmpbuf))
358
{
359
case 0:
360
(void)doit(p);
361
longjmp(*jmpbuf, 1);
362
break;
363
364
case 1:
365
break;
366
367
case 2:
368
VAR_HEAD = (LIST *)headsave;
369
break;
370
371
case 3:
372
goto ret;
373
break;
374
}
375
}
376
}
377
378
ret:
379
380
jmpbuf = savejmp;
381
382
FREEMEM(q);
383
384
return math_out_str;
385
}
386
387
VARIABLE *com_quit(void)
388
/*======================================================================
389
? Quit current doread entry by longjumping back to it (nasty).
390
& longjmp
391
~ doread
392
^=====================================================================*/
393
{
394
longjmp(*jmpbuf, 3);
395
396
return (VARIABLE *)NULL; /* won't be executed (hopefully) */
397
}
398
399
int dogets(char *buff, char *prompt)
400
/*======================================================================
401
? Get line from input stream. If both input & output streams are
402
| connected to terminal, this function gives user one of three
403
| (default) prompts:
404
|
405
| MATC>
406
| - normal prompt (PMODE_MAIN)
407
| ....>
408
| - begin end- block is being defined (PMODE_BLOCK)
409
| ####> (PMODE_CONT)
410
| - user has given a #-sign as a last character of
411
| previous line, this line will be concatenated with it
412
|
413
| If current comment character is found from input stream, the
414
| line after this character is discarded. Likewise if current
415
| system command character is found, the rest of the line is
416
| passed to system()-call.
417
|
418
= line got -> TRUE, EOF -> FALSE
419
! There should be a way to get an echo when reading from file.
420
& fprintf(), isatty(), fileno(), strlen(), fgets(), system()
421
^=====================================================================*/
422
{
423
char *ptr = buff, *p; /* Can't get rid of these. */
424
425
if ( !math_in ) return FALSE;
426
427
/*
428
Try figuring out if input & output streams are
429
terminals, if they both are, give user a prompt.
430
*/
431
if (isatty(fileno(math_in)) && isatty(fileno(math_out)))
432
PrintOut( "%s", prompt );
433
434
/*
435
i'm not in the mood to explain this.
436
*/
437
*ptr++ = ' ';
438
439
/*
440
Go for it.
441
*/
442
while((ptr = fgets(ptr, 256, math_in)) != NULL)
443
{
444
445
ptr[strlen(ptr)-1] = '\0';
446
447
/*
448
* Check if the user wants to continue with this line.
449
*/
450
while(ptr[strlen(ptr)-1] == '\\')
451
{
452
ptr += strlen(ptr) - 1;
453
dogets(ptr, PMODE_CONT);
454
}
455
456
/*
457
* if there is only spaces in this line,
458
* don't bother returning it, instead
459
* let's read afresh, otherwise return.
460
*/
461
p = ptr; while(isspace(*p)) p++;
462
463
if (*p != '\0') /* GOOD EXIT HERE */
464
{
465
#if 0
466
/*
467
* Look for the system character, if found
468
* pass rest of the line to system()-call
469
*/
470
for(p = buff; *p; p++)
471
{
472
switch(*p)
473
{
474
case SYSTEM:
475
system(p + 1);
476
PrintOut("\n");
477
*p = '\0'; p--;
478
break;
479
}
480
}
481
#endif
482
if (*buff != '\0')
483
return TRUE; /* OR IF WE ARE HONEST, IT'S HERE */
484
}
485
486
/*
487
if it's terminal give a prompt.
488
*/
489
if (isatty(fileno(math_in)) && isatty(fileno(math_out)))
490
PrintOut("%s", prompt);
491
}
492
493
return FALSE;
494
}
495
496
497
void com_init(char *word, int flag_pw, int flag_ce, VARIABLE *(*sub)(),
498
int minp, int maxp, char *help_text )
499
/*======================================================================
500
? Adds commands to global command list.
501
|
502
| Parameters:
503
| char *word
504
| - the keyword user gives for this command to be executed.
505
| int flag_pw
506
| - flag telling if the command can be executed element
507
| by element using function *(*sub)().
508
| int flag_ce
509
| - flag telling if the command can be executed when
510
| preprocessing if constant arguments
511
| double *(*sub)()
512
| - function to be executed when this command is given
513
| int minp, maxp
514
| - maximum and minimum number of parameters to command
515
|
516
| The global list of available commands is updated (or created if
517
| nonexistent).
518
|
519
& lst_add()
520
~ *_com_init()
521
^=====================================================================*/
522
{
523
COMMAND *ptr; /* can't get rid of this */
524
525
526
/*
527
Fill the structure...
528
*/
529
ptr = (COMMAND *)ALLOCMEM(COMSIZE);
530
NAME(ptr) = STRCOPY(word);
531
if (flag_pw)
532
ptr->flags |= CMDFLAG_PW;
533
if (flag_ce)
534
ptr->flags |= CMDFLAG_CE;
535
ptr->minp = minp;
536
ptr->maxp = maxp;
537
ptr->sub = sub;
538
ptr->help = help_text;
539
540
/*
541
...and update the list.
542
*/
543
lst_add(COMMANDS, (LIST *)ptr);
544
545
return;
546
}
547
548
void com_free(void)
549
/*======================================================================
550
? Deletes the list of commands and frees associated memory.
551
|
552
& lst_purge()
553
^=====================================================================*/
554
{
555
/*
556
Give memory back to system
557
*/
558
lst_purge(COMMANDS);
559
560
return;
561
}
562
563
COMMAND *com_check(char *str)
564
/*======================================================================
565
? Look for command from COMMANDS list by name.
566
|
567
= COMMAND *NULL if does not exist, pointer to command otherwise
568
& lst_find()
569
^=====================================================================*/
570
{
571
return (COMMAND *)lst_find(COMMANDS, str);
572
}
573
574
VARIABLE *com_help( VARIABLE *ptr )
575
/*======================================================================
576
? Print list of commands and user defined functions from global lists.
577
|
578
! The command to get here is "help" but it really is not very helpful.
579
|
580
& lst_print()
581
^=====================================================================*/
582
{
583
COMMAND *cmd;
584
FUNCTION *fnc;
585
char *name;
586
587
if ( !ptr )
588
{
589
590
lst_print(COMMANDS);
591
lst_print(FUNCTIONS);
592
593
} else {
594
595
name = var_to_string( ptr );
596
597
if ( (cmd = com_check( name ) ) != (COMMAND *)NULL )
598
{
599
600
if ( cmd->help )
601
PrintOut( "\n%s\n", cmd->help );
602
else
603
PrintOut( "\nSorry: no help available on [%s].\n", name );
604
605
} else if ( (fnc = fnc_check( name ) ) != (FUNCTION *)NULL )
606
{
607
608
if ( fnc->help )
609
PrintOut( "\n%s", fnc->help );
610
else
611
PrintOut( "\nSorry: no help available on [%s].\n", name );
612
613
} else {
614
615
error( "help: symbol not found: [%s]\n", name );
616
617
}
618
619
FREEMEM( name );
620
}
621
622
return (VARIABLE *)NULL;
623
}
624
625
VARIABLE *com_pointw(double (*sub)(), VARIABLE *ptr)
626
/*======================================================================
627
? This routine does a function call (*sub)(), for each element in
628
| matrix given by ptr.
629
|
630
= a temporary VARIABLE for which M(res, i, j) = (*sub)(M(ptr, i, j)
631
& var_temp_new(), *(sub)()
632
^=====================================================================*/
633
{
634
VARIABLE *res,*ptr2; /* pointer to result structure */
635
636
double *a, *a2, *a3, *b; /* pointer to matrices */
637
int n, m, sz; /* matrix dimensions */
638
639
int i; /* loop index */
640
641
/*
642
Get space for result and ...
643
*/
644
n = NROW(ptr); m = NCOL(ptr);
645
res = var_temp_new(TYPE(ptr) ,n , m);
646
647
sz = n*m;
648
a = MATR(ptr); b = MATR(res);
649
650
/*
651
...to action.
652
*/
653
ptr2 = NEXT(ptr);
654
if(ptr2)
655
{
656
if(n!=NROW(ptr2)||m!=NCOL(ptr2))
657
{
658
error("Pointwise function arguments must all be of same size.");
659
}
660
a2 = MATR(ptr2);
661
662
ptr2 = NEXT(ptr2);
663
if(ptr2)
664
{
665
if(n!=NROW(ptr2)||m!=NCOL(ptr2))
666
{
667
error("Pointwise function arguments must all be of same size,");
668
}
669
if(NEXT(ptr2))
670
{
671
error("Currently at most three arguments for pointwise functions allowed, sorry.");
672
}
673
a3 = MATR(ptr2);
674
for(i = 0; i < sz; i++)
675
*b++ = ((double (*)(double, double, double)) sub)(*a++, *a2++, *a3++);
676
}
677
else
678
{
679
for(i = 0; i < sz; i++)
680
*b++ = ((double (*)(double, double)) sub)(*a++, *a2++);
681
}
682
}
683
else
684
{
685
for(i = 0; i < sz; i++)
686
*b++ = ((double (*)(double)) sub)(*a++);
687
}
688
689
return res;
690
}
691
692
VARIABLE *com_el(VARIABLE *ptr)
693
/*======================================================================
694
? Extracts specified elements from a matrix. Indexes are given by two
695
| column vectors. The values of the elements of these vectors give
696
| the required indexes. If there is only one index vector given
697
| it is assumed to be column index and row index is set to scalar 0.
698
|
699
| If matrix x is, for example,
700
|
701
| 1 2
702
| 3 4
703
|
704
| you get the first row by
705
|
706
| x[0, 0 1]
707
|
708
| or by
709
|
710
| x(0 1)
711
|
712
= A new temporary VARIABLE, whose size equals to
713
| number of row indexes times number of column indexes.
714
|
715
& var_temp_new(), var_delete_temp()
716
^=====================================================================*/
717
{
718
VARIABLE *res, /* result ... */
719
*par = NEXT(ptr); /* pointer to list of VARIABLES */
720
/* containing indexes */
721
722
static double defind = 0.0;
723
#pragma omp threadprivate (defind)
724
double *ind1 = &defind, *ind2;
725
726
int i, j, k, /* loop indexes */
727
rows, cols, /* no. of rows and columns in the matrix */
728
/* to be indexed. */
729
size1 = 1, size2,
730
ind;
731
732
rows = NROW(ptr); cols = NCOL(ptr);
733
734
/*
735
* check if scalar ....
736
*/
737
if (rows == 1 && cols == 1)
738
{
739
if (*MATR(par) != 0) error("Index out of bounds.\n");
740
if (NEXT(par) != NULL)
741
if (*MATR(NEXT(par)) != 0) error("Index out of bounds.\n");
742
res = var_temp_new(TYPE(ptr),1,1);
743
*MATR(res) = *MATR(ptr);
744
return res;
745
}
746
747
/*
748
The matrix will be indexed by two column vectors.
749
If there is just one assume it's column index and
750
make rowindex 0.
751
*/
752
if (NEXT(par) == NULL)
753
{
754
if (NROW(par) == rows && NCOL(par) == cols)
755
{
756
int logical = TRUE,
757
onecount=0;
758
759
double *dtmp;
760
761
dtmp = MATR(par);
762
for(i = 0; i < NROW(par)*NCOL(par); i++)
763
if (dtmp[i] == 0)
764
{
765
}
766
else if (dtmp[i] == 1)
767
{
768
onecount++;
769
}
770
else
771
{
772
logical = FALSE;
773
break;
774
}
775
776
if (logical)
777
{
778
if (onecount == 0) return NULL;
779
780
res = var_temp_new(TYPE(ptr),1,onecount);
781
for(i=0,k=0; i < rows; i++)
782
for(j=0; j < cols; j++)
783
if (M(par,i,j) == 1)
784
{
785
memcpy(&M(res,0,k++),&M(ptr,i,j),sizeof(double));
786
}
787
return res;
788
}
789
}
790
791
ind2 = MATR(par); size2 = NCOL(par);
792
cols *= rows; rows = 1;
793
}
794
else
795
{
796
ind1 = MATR(par); size1 = NCOL(par);
797
size2 = NCOL(NEXT(par));
798
ind2 = MATR(NEXT(par));
799
}
800
801
/*
802
Space for result
803
*/
804
res = var_temp_new(TYPE(ptr), size1, size2);
805
806
/*
807
Extract the values (try making sense out of that
808
if you feel like it).
809
*/
810
for(i = 0; i < size1; i++)
811
{
812
ind = (int)ind1[i];
813
for(j = 0; j < size2; j++)
814
if (ind < rows && (int)ind2[j] < cols)
815
memcpy(&M(res,i,j),&M(ptr,ind,(int)ind2[j]),sizeof(double));
816
else
817
error("Index out of bounds.\n");
818
}
819
820
return res;
821
}
822
823
VARIABLE *com_source(VARIABLE *ptr)
824
/*======================================================================
825
? Redirect input stream to a file, whose name is given.
826
|
827
@ FILE *math_in
828
& ALLOCMEM, FREEMEM, fopen(), fclose(), error()
829
^=====================================================================*/
830
{
831
char *name; /* Hold converted string (file name) */
832
833
FILE *save_in = math_in; /* Save previous input stream until */
834
/* we are done with the new file. */
835
836
/*
837
convert the file name from ptr.
838
*/
839
name = var_to_string(ptr);
840
841
/*
842
Execute the file.
843
*/
844
if ((math_in = fopen(name,"r")) != NULL)
845
{
846
/* PrintOut("Executing commands from file, %s...\n", name); */
847
doread();
848
fclose(math_in);
849
}
850
else
851
{
852
PrintOut( "Source: Can't open file, %s.\n",name );
853
}
854
855
math_in = save_in;
856
FREEMEM(name);
857
858
return (VARIABLE *)NULL;
859
}
860
861
862
VARIABLE *com_apply(VARIABLE *ptr)
863
/*======================================================================
864
? Executes given string.
865
|
866
& ALLOCMEM, FREEMEM, doit()
867
^=====================================================================*/
868
{
869
VARIABLE *res; /* result pointer */
870
871
char *p, *q; /* holds the string to be executed, after */
872
/* conversion from structure VARIABLE * */
873
874
int i, j; /* just loop indexes */
875
876
877
/*
878
Allocate space for the string...
879
*/
880
p = q = ALLOCMEM(NROW(ptr) * NCOL(ptr) + 1);
881
882
/*
883
... convert it ...
884
*/
885
for(i = 0; i < NROW(ptr); i++)
886
for(j = 0; j < NCOL(ptr); j++)
887
*p++ = (char)M(ptr,i,j);
888
889
*p = '\0';
890
891
/*
892
... and try executing it.
893
*/
894
res = doit( q );
895
896
FREEMEM(q);
897
898
return res;
899
}
900
901
void mem_free(void *mem)
902
/*======================================================================
903
? Free memory given by argument, and unlink it from allocation list.
904
| Currently FREEMEM(ptr) is defined to be mem_free(ptr).
905
|
906
& free()
907
~ mem_alloc(), mem_free_all()
908
^=====================================================================*/
909
{
910
ALLOC_LIST *lst;
911
912
#ifdef DEBUG
913
tot--; fprintf(fplog,"free addr: %d total: %d\n", ALLOC_LST(mem), tot);
914
fflush( fplog );
915
#endif
916
/*
917
if the list is empty return
918
*/
919
if ( (lst = (ALLOC_LIST *)ALLOC_HEAD) == (ALLOC_LIST *)NULL )
920
{
921
#if 1
922
/* ????? */
923
free( ALLOC_LST(mem) );
924
#else
925
fprintf( stderr, "SHOULD THIS HAPPEN ????\n" );
926
#endif
927
return;
928
}
929
930
/*
931
* it's not the header, look if it's in list at all
932
*/
933
if (ALLOC_PTR(lst) != mem)
934
{
935
936
for(; NEXT(lst); lst = NEXT(lst))
937
{
938
if (ALLOC_PTR(NEXT(lst)) == mem) break;
939
}
940
941
/*
942
* item was not found from the list. free ptr and return.
943
*/
944
if (NEXT(lst) == (ALLOC_LIST *)NULL)
945
{
946
free(ALLOC_LST(mem));
947
return;
948
}
949
950
/*
951
* unlink
952
*/
953
NEXT(lst) = NEXT(NEXT(lst));
954
}
955
956
/*
957
* item was the header, unlink it
958
*/
959
else
960
ALLOC_HEAD = NEXT(ALLOC_HEAD);
961
962
/*
963
* and at last return memory back to system
964
*/
965
free(ALLOC_LST(mem));
966
967
return;
968
}
969
970
void mem_free_all(void)
971
/*======================================================================
972
? Free all memory allocated since last entry of doread.
973
| (actually free all memory from list ALLOCATIONS).
974
|
975
~ mem_alloc(), mem_free(), doread(), error()
976
^=====================================================================*/
977
{
978
ALLOC_LIST *lst, *lstn;
979
980
for(lst = (ALLOC_LIST *)ALLOC_HEAD; lst;)
981
{
982
#ifdef DEBUG
983
tot--; fprintf(fplog,"freeall addr: %d total: %d\n", lst, tot);
984
fflush( fplog );
985
#endif
986
lstn = NEXT(lst);
987
free( (char *)lst );
988
lst = lstn;
989
}
990
991
ALLOC_HEAD = (LIST *)NULL; /* security */
992
993
return;
994
}
995
996
void *mem_alloc(size_t size)
997
/*======================================================================
998
? Allocate memory and link it to memory allocation list.
999
|
1000
~ calloc(), free(), error()
1001
^=====================================================================*/
1002
{
1003
ALLOC_LIST *lst;
1004
1005
/*
1006
* try allocating memory
1007
*/
1008
if ((lst = (ALLOC_LIST *)calloc(size+sizeof(ALLOC_LIST), 1)) != NULL)
1009
{
1010
NEXT(lst) = (ALLOC_LIST *)ALLOC_HEAD; ALLOC_HEAD = (LIST *)lst;
1011
}
1012
else
1013
error("Can't alloc mem.\n");
1014
1015
#ifdef DEBUG
1016
tot++; fprintf(fplog,"alloc addr: %d size: %d total: %d\n",
1017
lst, size, tot);
1018
fflush( fplog );
1019
#endif
1020
return ALLOC_PTR(lst);
1021
}
1022
1023