1 
2 /***************************************************************************
3                                                                            *
4 Copyright 2012 CertiVox IOM Ltd.                                           *
5                                                                            *
6 This file is part of CertiVox MIRACL Crypto SDK.                           *
7                                                                            *
8 The CertiVox MIRACL Crypto SDK provides developers with an                 *
9 extensive and efficient set of cryptographic functions.                    *
10 For further information about its features and functionalities please      *
11 refer to http://www.certivox.com                                           *
12                                                                            *
13 * The CertiVox MIRACL Crypto SDK is free software: you can                 *
14   redistribute it and/or modify it under the terms of the                  *
15   GNU Affero General Public License as published by the                    *
16   Free Software Foundation, either version 3 of the License,               *
17   or (at your option) any later version.                                   *
18                                                                            *
19 * The CertiVox MIRACL Crypto SDK is distributed in the hope                *
20   that it will be useful, but WITHOUT ANY WARRANTY; without even the       *
21   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
22   See the GNU Affero General Public License for more details.              *
23                                                                            *
24 * You should have received a copy of the GNU Affero General Public         *
25   License along with CertiVox MIRACL Crypto SDK.                           *
26   If not, see <http://www.gnu.org/licenses/>.                              *
27                                                                            *
28 You can be released from the requirements of the license by purchasing     *
29 a commercial license. Buying such a license is mandatory as soon as you    *
30 develop commercial activities involving the CertiVox MIRACL Crypto SDK     *
31 without disclosing the source code of your own applications, or shipping   *
32 the CertiVox MIRACL Crypto SDK with a closed source product.               *
33                                                                            *
34 ***************************************************************************/
35 /* mex.c
36  *
37  * Updated to allow emission of scheduled code.
38  *
39  * Macro EXpansion program.
40  * Expands Macros from a .mcs file into a .tpl file to create a .c file
41  *
42  */
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 
48 typedef int BOOL;
49 #define FALSE 0
50 #define TRUE 1
51 
52 /* Define Algorithms */
53 
54 #define MULTIPLY 0
55 #define MULTUP 1
56 #define SQUARE 2
57 #define REDC 3
58 #define ADDITION 4
59 #define INCREMENT 5
60 #define SUBTRACTION 6
61 #define DECREMENT 7
62 #define SUMMATION 8
63 #define INCREMENTATION 9
64 #define DECREMENTATION 10
65 #define MULTIPLY2 11
66 #define ADDITION2 12
67 #define SUBTRACTION2 13
68 #define PMULT 14
69 #define DOUBLEIT 15
70 
71 
72 /* Define Macros */
73 
74 #define MUL_START       0
75 #define STEP            1
76 #define STEP1M          2
77 #define STEP1A          3
78 #define STEP2M          4
79 #define STEP2A          5
80 #define MFIN            6
81 #define MUL_END         7
82 #define LAST            8
83 #define SQR_START       9
84 #define DSTEP           10
85 #define DSTEP1M         11
86 #define DSTEP1A         12
87 #define DSTEP2M         13
88 #define DSTEP2A         14
89 #define SELF            15
90 #define SFIN            16
91 #define SQR_END         17
92 #define REDC_START      18
93 #define RFINU           19
94 #define RFIND           20
95 #define REDC_END        21
96 #define ADD_START       22
97 #define ADD             23
98 #define ADD_END         24
99 #define SUB_START       25
100 #define SUB             26
101 #define SUB_END         27
102 #define INC_START       28
103 #define INC             29
104 #define INC_END         30
105 #define DEC_START       31
106 #define DEC             32
107 #define DEC_END         33
108 #define KADD_START      34
109 #define KASL            35
110 #define KADD_END        36
111 #define KINC_START      37
112 #define KIDL            38
113 #define KINC_END        39
114 #define KDEC_START      40
115 #define KDEC_END        41
116 #define STEPB           42
117 #define STEPB1M         43
118 #define STEPB1A         44
119 #define STEPB2M         45
120 #define STEPB2A         46
121 #define H2_MUL_START    47
122 #define H2_STEP         48
123 #define H2_MFIN         49
124 #define H2_MUL_END      50
125 #define H2_SQR_START    51
126 #define H2_DSTEP        52
127 #define H2_SELF         53
128 #define H2_SFIN         54
129 #define H2_SQR_END      55
130 #define H4_MUL_START    56
131 #define H4_STEP         57
132 #define H4_MFIN         58
133 #define H4_MUL_END      59
134 #define H4_SQR_START    60
135 #define H4_DSTEP        61
136 #define H4_SELF         62
137 #define H4_SFIN         63
138 #define H4_SQR_END      64
139 #define H2_LAST         65
140 #define H4_LAST         66
141 #define PMUL_START      67
142 #define PMUL            68
143 #define PMUL_END        69
144 #define MULB_START      70
145 #define MULB_END        71
146 #define MBFIN           72
147 #define H2_MULB_START   73
148 #define H2_MULB_END     74
149 #define H2_MBFIN        75
150 #define H2_STEPB        76
151 #define H4_MULB_START   77
152 #define H4_MULB_END     78
153 #define H4_MBFIN        79
154 #define H4_STEPB        80
155 #define H2_REDC_START   81
156 #define H2_RFINU        82
157 #define H2_RFIND        83
158 #define H2_REDC_END     84
159 #define H4_REDC_START   85
160 #define H4_RFINU        86
161 #define H4_RFIND        87
162 #define H4_REDC_END     88
163 #define DOUBLE_START    89
164 #define DOUBLE          90
165 #define DOUBLE_END      91
166 #define LAST_ONE        92
167 
168 BOOL scheduled;
169 int hybrid,hybrid_b,pmp,hybrid_r;
170 
171 int PARAM;
172 char *macro[LAST_ONE]; /* macro text */
173 
174 char *functions[]={(char *)"MULTIPLY",(char *)"MULTUP",(char *)"SQUARE",(char *)"REDC",(char *)"ADDITION",(char *)"INCREMENT",
175                  (char *)"SUBTRACTION",(char *)"DECREMENT",(char *)"SUMMATION",(char *)"INCREMENTATION",
176                  (char *)"DECREMENTATION",(char *)"MULTIPLY2",(char *)"ADDITION2",(char *)"SUBTRACTION2",(char *)"PMULT",(char *)"DOUBLEIT",NULL};
177 
178 char *names[]={(char *)"MUL_START",(char *)"STEP",(char *)"STEP1M",(char *)"STEP1A",(char *)"STEP2M",
179                (char *)"STEP2A",(char *)"MFIN",(char *)"MUL_END",(char *)"LAST",(char *)"SQR_START",(char *)"DSTEP",
180                (char *)"DSTEP1M",(char *)"DSTEP1A",(char *)"DSTEP2M",(char *)"DSTEP2A",(char *)"SELF",
181                (char *)"SFIN",(char *)"SQR_END",(char *)"REDC_START",(char *)"RFINU",(char *)"RFIND",
182                (char *)"REDC_END",(char *)"ADD_START",(char *)"ADD",(char *)"ADD_END",(char *)"SUB_START",(char *)"SUB",
183                (char *)"SUB_END",(char *)"INC_START",(char *)"INC",(char *)"INC_END",(char *)"DEC_START",(char *)"DEC",
184                (char *)"DEC_END",(char *)"KADD_START",(char *)"KASL",(char *)"KADD_END",(char *)"KINC_START",(char *)"KIDL",
185                (char *)"KINC_END",(char *)"KDEC_START",(char *)"KDEC_END",(char *)"STEPB",(char *)"STEPB1M",(char *)"STEPB1A",(char *)"STEPB2M",(char *)"STEPB2A",
186                (char *)"H2_MUL_START",(char *)"H2_STEP",(char *)"H2_MFIN",(char *)"H2_MUL_END",
187                (char *)"H2_SQR_START",(char *)"H2_DSTEP",(char *)"H2_SELF",(char *)"H2_SFIN",(char *)"H2_SQR_END",
188                (char *)"H4_MUL_START",(char *)"H4_STEP",(char *)"H4_MFIN",(char *)"H4_MUL_END",
189                (char *)"H4_SQR_START",(char *)"H4_DSTEP",(char *)"H4_SELF",(char *)"H4_SFIN",(char *)"H4_SQR_END",(char *)"H2_LAST",(char *)"H4_LAST",
190                 (char *)"PMUL_START",(char *)"PMUL",(char *)"PMUL_END",(char *)"MULB_START",(char *)"MULB_END",(char *)"MBFIN",
191                 (char *)"H2_MULB_START",(char *)"H2_MULB_END",(char *)"H2_MBFIN",(char *)"H2_STEPB",
192                 (char *)"H4_MULB_START",(char *)"H4_MULB_END",(char *)"H4_MBFIN",(char *)"H4_STEPB",
193                 (char *)"H2_REDC_START",(char *)"H2_RFINU",(char *)"H2_RFIND",(char *)"H2_REDC_END",
194                 (char *)"H4_REDC_START",(char *)"H4_RFINU",(char *)"H4_RFIND",(char *)"H4_REDC_END",
195                 (char *)"DOUBLE_START",(char *)"DOUBLE",(char *)"DOUBLE_END",NULL};
196 
white(char c)197 BOOL white(char c)
198 {
199     if (c==' ' || c=='\n' || c=='\r' || c=='\t') return TRUE;
200     else return FALSE;
201 }
202 
skip(char * c,int i)203 int skip(char *c,int i)
204 {
205     while (white(c[i])) i++;
206     return i;
207 }
208 
which(char * name,char * names[])209 int which(char *name,char *names[])
210 {
211     int ipt=0;
212     while (names[ipt]!=NULL)
213     {
214         if (strcmp(name,names[ipt])==0) return ipt;
215         ipt++;
216     }
217     return -1;
218 }
219 
m_prologue(FILE * dotc,int k,int m)220 void m_prologue(FILE *dotc,int k,int m)
221 {
222     fprintf(dotc,macro[STEP1M],k,m);
223 }
224 
m_epilogue(FILE * dotc,int x)225 void m_epilogue(FILE *dotc,int x)
226 {
227     if (x==1) fprintf(dotc,macro[STEP1A]);
228     else      fprintf(dotc,macro[STEP2A]);
229 }
230 
m_schedule(FILE * dotc,int x,int k,int m)231 void m_schedule(FILE *dotc,int x,int k,int m)
232 {
233     if (x==1)
234     {
235         fprintf(dotc,macro[STEP2M],k,m);
236         fprintf(dotc,macro[STEP1A]);
237     }
238     else
239     {
240         fprintf(dotc,macro[STEP1M],k,m);
241         fprintf(dotc,macro[STEP2A]);
242     }
243 }
244 
m_prologue2(FILE * dotc,int k,int m)245 void m_prologue2(FILE *dotc,int k,int m)
246 {
247     fprintf(dotc,macro[STEPB1M],k,m);
248 }
249 
m_epilogue2(FILE * dotc,int x)250 void m_epilogue2(FILE *dotc,int x)
251 {
252     if (x==1) fprintf(dotc,macro[STEPB1A]);
253     else      fprintf(dotc,macro[STEPB2A]);
254 }
255 
m_schedule2(FILE * dotc,int x,int k,int m)256 void m_schedule2(FILE *dotc,int x,int k,int m)
257 {
258     if (x==1)
259     {
260         fprintf(dotc,macro[STEPB2M],k,m);
261         fprintf(dotc,macro[STEPB1A]);
262     }
263     else
264     {
265         fprintf(dotc,macro[STEPB1M],k,m);
266         fprintf(dotc,macro[STEPB2A]);
267     }
268 }
269 
s_prologue(FILE * dotc,int k,int m)270 void s_prologue(FILE *dotc,int k,int m)
271 {
272     fprintf(dotc,macro[DSTEP1M],k,m);
273 }
274 
s_epilogue(FILE * dotc,int x)275 void s_epilogue(FILE *dotc,int x)
276 {
277     if (x==1) fprintf(dotc,macro[DSTEP1A]);
278     else      fprintf(dotc,macro[DSTEP2A]);
279 }
280 
s_schedule(FILE * dotc,int x,int k,int m)281 void s_schedule(FILE *dotc,int x,int k,int m)
282 {
283     if (x==1)
284     {
285         fprintf(dotc,macro[DSTEP2M],k,m);
286         fprintf(dotc,macro[DSTEP1A]);
287     }
288     else
289     {
290         fprintf(dotc,macro[DSTEP1M],k,m);
291         fprintf(dotc,macro[DSTEP2A]);
292     }
293 }
294 
295 /* Insert functions into template file */
296 
insert(int index,FILE * dotc)297 void insert(int index,FILE *dotc)
298 {
299     int i,k,m,n,x,inc;
300     switch (index)
301     {
302     case PMULT:
303         if (!pmp) break;
304         fprintf(dotc,macro[PMUL_START]);
305         for (i=0;i<PARAM;i++)
306         {
307             fprintf(dotc,macro[PMUL],i,i,i);
308         }
309         fprintf(dotc,macro[PMUL_END]);
310         break;
311     case MULTIPLY2:
312         inc=1;
313         if (hybrid_b)
314         {
315             inc=hybrid_b;
316             if (hybrid_b==2)  fprintf(dotc,macro[H2_MULB_START]);
317             if (hybrid_b==4)  fprintf(dotc,macro[H4_MULB_START]);
318         }
319         else fprintf(dotc,macro[MULB_START]);
320         for (i=n=0;i<PARAM;i+=inc,n+=inc)
321         {
322             k=0; m=i;
323             if (scheduled)
324             {
325                 x=1;
326                 m_prologue2(dotc,k,m);
327                 k++; m--;
328 
329                 while (k<=i)
330                 {
331                     m_schedule2(dotc,x,k,m);
332                     k++; m--;
333                     x=3-x;
334                 }
335 
336                 m_epilogue2(dotc,x);
337 
338             }
339             else
340             {
341                 while (k<=i)
342                 {
343                     if (hybrid_b)
344                     {
345                         if (hybrid_b==2) fprintf(dotc,macro[H2_STEPB],k,k,m,m);
346                         if (hybrid_b==4) fprintf(dotc,macro[H4_STEPB],k,k,k,k,m,m,m,m);
347                     }
348                     else fprintf(dotc,macro[STEPB],k,m);
349                     k+=inc; m-=inc;
350                 }
351 
352             }
353             if (hybrid_b)
354             {
355                 if (hybrid_b==2) fprintf(dotc,macro[H2_MBFIN],n,n+1);
356                 if (hybrid_b==4) fprintf(dotc,macro[H4_MBFIN],n,n+1,n+2,n+3);
357             }
358             else fprintf(dotc,macro[MBFIN],n);
359 
360         }
361         for (i=0;i<PARAM-inc;i+=inc,n+=inc)
362         {
363             k=i+inc; m=PARAM-inc;
364             if (scheduled)
365             {
366                 x=1;
367                 m_prologue2(dotc,k,m);
368                 k++; m--;
369 
370                 while (k<=PARAM-1)
371                 {
372                     m_schedule2(dotc,x,k,m);
373                     k++; m--;
374                     x=3-x;
375                 }
376                 m_epilogue2(dotc,x);
377             }
378             else
379             {
380                 while (k<=PARAM-inc)
381                 {
382                     if (hybrid_b)
383                     {
384                         if (hybrid_b==2) fprintf(dotc,macro[H2_STEPB],k,k,m,m);
385                         if (hybrid_b==4) fprintf(dotc,macro[H4_STEPB],k,k,k,k,m,m,m,m);
386                     }
387                     else fprintf(dotc,macro[STEPB],k,m);
388                     k+=inc; m-=inc;
389                 }
390             }
391             if (hybrid_b)
392             {
393                 if (hybrid_b==2) fprintf(dotc,macro[H2_MBFIN],n,n+1);
394                 if (hybrid_b==4) fprintf(dotc,macro[H4_MBFIN],n,n+1,n+2,n+3);
395             }
396             else fprintf(dotc,macro[MBFIN],n);
397 
398         }
399 
400         if (hybrid_b)
401         {
402             if (hybrid_b==2) fprintf(dotc,macro[H2_MULB_END],2*PARAM-2);
403             if (hybrid_b==4) fprintf(dotc,macro[H4_MULB_END],2*PARAM-4,2*PARAM-3,2*PARAM-2);
404         }
405         else fprintf(dotc,macro[MULB_END]);
406     break;
407     case MULTIPLY:
408         inc=1;
409         if (hybrid)
410         {
411             inc=hybrid;
412             if (hybrid==2)  fprintf(dotc,macro[H2_MUL_START]);
413             if (hybrid==4)  fprintf(dotc,macro[H4_MUL_START]);
414         }
415         else fprintf(dotc,macro[MUL_START]);
416         for (i=n=0;i<PARAM;i+=inc,n+=inc)
417         {
418             k=0; m=i;
419 
420             if (scheduled)
421             {
422                 x=1;
423                 m_prologue(dotc,k,m);
424                 k++; m--;
425 
426                 while (k<=i)
427                 {
428                     m_schedule(dotc,x,k,m);
429                     k++; m--;
430                     x=3-x;
431                 }
432 
433                 m_epilogue(dotc,x);
434 
435             }
436             else
437             {
438                 while (k<=i)
439                 {
440                     if (hybrid)
441                     {
442                         if (hybrid==2) fprintf(dotc,macro[H2_STEP],k,k,m,m);
443                         if (hybrid==4) fprintf(dotc,macro[H4_STEP],k,k,k,k,m,m,m,m);
444                     }
445                     else fprintf(dotc,macro[STEP],k,m);
446                     k+=inc; m-=inc;
447                 }
448             }
449             if (hybrid)
450             {
451                 if (hybrid==2) fprintf(dotc,macro[H2_MFIN],n,n+1);
452                 if (hybrid==4) fprintf(dotc,macro[H4_MFIN],n,n+1,n+2,n+3);
453             }
454             else fprintf(dotc,macro[MFIN],n);
455         }
456         for (i=0;i<PARAM-inc;i+=inc,n+=inc)
457         {
458             k=i+inc; m=PARAM-inc;
459 
460             if (scheduled)
461             {
462                 x=1;
463                 m_prologue(dotc,k,m);
464                 k++; m--;
465 
466                 while (k<=PARAM-1)
467                 {
468                     m_schedule(dotc,x,k,m);
469                     k++; m--;
470                     x=3-x;
471                 }
472                 m_epilogue(dotc,x);
473             }
474             else
475             {
476                 while (k<=PARAM-inc)
477                 {
478                     if (hybrid)
479                     {
480                         if (hybrid==2) fprintf(dotc,macro[H2_STEP],k,k,m,m);
481                         if (hybrid==4) fprintf(dotc,macro[H4_STEP],k,k,k,k,m,m,m,m);
482                     }
483                     else fprintf(dotc,macro[STEP],k,m);
484                     k+=inc; m-=inc;
485                 }
486             }
487             if (hybrid)
488             {
489                 if (hybrid==2) fprintf(dotc,macro[H2_MFIN],n,n+1);
490                 if (hybrid==4) fprintf(dotc,macro[H4_MFIN],n,n+1,n+2,n+3);
491             }
492             else fprintf(dotc,macro[MFIN],n);
493         }
494         if (hybrid)
495         {
496             if (hybrid==2) fprintf(dotc,macro[H2_MUL_END],2*PARAM-2,2*PARAM-1);
497             if (hybrid==4) fprintf(dotc,macro[H4_MUL_END],2*PARAM-4,2*PARAM-3,2*PARAM-2,2*PARAM-1);
498         }
499         else fprintf(dotc,macro[MUL_END],2*PARAM-1);
500         break;
501     case MULTUP:
502         inc=1;
503         if (hybrid)
504         {
505             inc=hybrid;
506             if (hybrid==2)  fprintf(dotc,macro[H2_MUL_START]);
507             if (hybrid==4)  fprintf(dotc,macro[H4_MUL_START]);
508         }
509         else fprintf(dotc,macro[MUL_START]);
510 
511         for (i=n=0;i<PARAM-inc;i+=inc,n+=inc)
512         {
513             k=0; m=i;
514 
515             if (scheduled)
516             {
517                 x=1;
518                 m_prologue(dotc,k,m);
519                 k++; m--;
520 
521                 while (k<=i)
522                 {
523                     m_schedule(dotc,x,k,m);
524                     k++; m--;
525                     x=3-x;
526                 }
527                 m_epilogue(dotc,x);
528             }
529             else
530             {
531                 while (k<=i)
532                 {
533                     if (hybrid)
534                     {
535                         if (hybrid==2) fprintf(dotc,macro[H2_STEP],k,k,m,m);
536                         if (hybrid==4) fprintf(dotc,macro[H4_STEP],k,k,k,k,m,m,m,m);
537                     }
538                     else fprintf(dotc,macro[STEP],k,m);
539                     k+=inc; m-=inc;
540                 }
541             }
542             if (hybrid)
543             {
544                 if (hybrid==2) fprintf(dotc,macro[H2_MFIN],n,n+1);
545                 if (hybrid==4) fprintf(dotc,macro[H4_MFIN],n,n+1,n+2,n+3);
546             }
547             else fprintf(dotc,macro[MFIN],n);
548         }
549         k=0; m=PARAM-inc;
550         while (k<=i)
551         {
552             if (hybrid)
553             {
554                 if (hybrid==2) fprintf(dotc,macro[H2_LAST],k,k,m,m);
555                 if (hybrid==4) fprintf(dotc,macro[H4_LAST],k,k,k,k,m,m,m,m);
556             }
557             else fprintf(dotc,macro[LAST],k,m);
558             k+=inc; m-=inc;
559         }
560 
561         if (hybrid)
562         {
563             if (hybrid==2) fprintf(dotc,macro[H2_MUL_END],PARAM-2,PARAM-1);
564             if (hybrid==4) fprintf(dotc,macro[H4_MUL_END],PARAM-4,PARAM-3,PARAM-2,PARAM-1);
565         }
566         else fprintf(dotc,macro[MUL_END],PARAM-1);
567         break;
568     case SQUARE:
569         inc=1;
570         if (hybrid)
571         {
572             inc=hybrid;
573             if (hybrid==2) fprintf(dotc,macro[H2_SQR_START]);
574             if (hybrid==4) fprintf(dotc,macro[H4_SQR_START]);
575         }
576         else fprintf(dotc,macro[SQR_START]);
577         for (i=n=0;i<PARAM;i+=inc,n+=inc)
578         {
579             k=0; m=i;
580 
581             if (scheduled)
582             {
583                 if (k<m)
584                 {
585                     x=1;
586                     s_prologue(dotc,k,m);
587                     k++; m--;
588 
589                     while (k<m)
590                     {
591                         s_schedule(dotc,x,k,m);
592                         k++; m--;
593                         x=3-x;
594                     }
595                    s_epilogue(dotc,x);
596                 }
597             }
598             else
599             {
600                 while (k<m)
601                 {
602                     if (hybrid)
603                     {
604                         if (hybrid==2) fprintf(dotc,macro[H2_DSTEP],k,k,m,m);
605                         if (hybrid==4) fprintf(dotc,macro[H4_DSTEP],k,k,k,k,m,m,m,m);
606                     }
607                     else fprintf(dotc,macro[DSTEP],k,m);
608                     k+=inc; m-=inc;
609                 }
610             }
611             if (hybrid)
612             {
613                 if (hybrid==2 && n%4==0) fprintf(dotc,macro[H2_SELF],n/2,n/2);
614                 if (hybrid==4 && n%8==0) fprintf(dotc,macro[H4_SELF],n/2,n/2,n/2,n/2);
615             }
616             else
617             {
618                 if (n%2==0) fprintf(dotc,macro[SELF],n/2,n/2);
619             }
620             if (hybrid)
621             {
622                 if (hybrid==2) fprintf(dotc,macro[H2_SFIN],n,n+1);
623                 if (hybrid==4) fprintf(dotc,macro[H4_SFIN],n,n+1,n+2,n+3);
624             }
625             else fprintf(dotc,macro[SFIN],n);
626         }
627         for (i=0;i<PARAM-inc;i+=inc,n+=inc)
628         {
629             k=i+inc; m=PARAM-inc;
630 
631             if (scheduled)
632             {
633                 if (k<m)
634                 {
635                     x=1;
636                     s_prologue(dotc,k,m);
637                     k++; m--;
638 
639                     while (k<m)
640                     {
641                         s_schedule(dotc,x,k,m);
642                         k++; m--;
643                         x=3-x;
644                     }
645                     s_epilogue(dotc,x);
646                 }
647             }
648             else
649             {
650                 while (k<m)
651                 {
652                     if (hybrid)
653                     {
654                         if (hybrid==2) fprintf(dotc,macro[H2_DSTEP],k,k,m,m);
655                         if (hybrid==4) fprintf(dotc,macro[H4_DSTEP],k,k,k,k,m,m,m,m);
656                     }
657                     else fprintf(dotc,macro[DSTEP],k,m);
658                     k+=inc; m-=inc;
659                 }
660             }
661             if (hybrid)
662             {
663                 if (hybrid==2 && n%4==0) fprintf(dotc,macro[H2_SELF],n/2,n/2);
664                 if (hybrid==4 && n%8==0) fprintf(dotc,macro[H4_SELF],n/2,n/2,n/2,n/2);
665             }
666             else
667             {
668                 if (n%2==0) fprintf(dotc,macro[SELF],n/2,n/2);
669             }
670             if (hybrid)
671             {
672                 if (hybrid==2) fprintf(dotc,macro[H2_SFIN],n,n+1);
673                 if (hybrid==4) fprintf(dotc,macro[H4_SFIN],n,n+1,n+2,n+3);
674             }
675             else fprintf(dotc,macro[SFIN],n);
676         }
677         if (hybrid)
678         {
679             if (hybrid==2) fprintf(dotc,macro[H2_SQR_END],2*PARAM-2,2*PARAM-1);
680             if (hybrid==4) fprintf(dotc,macro[H4_SQR_END],2*PARAM-4,2*PARAM-3,2*PARAM-2,2*PARAM-1);
681         }
682         else fprintf(dotc,macro[SQR_END],2*PARAM-1);
683         break;
684     case REDC:
685         inc=1;
686         if (hybrid_r)
687         {
688             inc=hybrid_r;
689             if (hybrid_r==2)
690             {
691                 fprintf(dotc,macro[H2_REDC_START]);
692                 fprintf(dotc,macro[H2_RFINU],0,0,0,0);
693             }
694             if (hybrid_r==4)
695             {
696                 fprintf(dotc,macro[H4_REDC_START]);
697                 fprintf(dotc,macro[H4_RFINU],0,0,0,0,0,0,0,0);
698             }
699         }
700         else
701         {
702             fprintf(dotc,macro[REDC_START]);
703             fprintf(dotc,macro[RFINU],0,0);
704         }
705 
706         for (i=n=inc;i<PARAM;i+=inc,n+=inc)
707         {
708             k=0; m=i;
709 
710             if (scheduled)
711             {
712                 x=1;
713                 m_prologue(dotc,k,m);
714                 k++; m--;
715 
716                 while (k<i)
717                 {
718                     m_schedule(dotc,x,k,m);
719                     k++; m--;
720                     x=3-x;
721                 }
722                 m_epilogue(dotc,x);
723             }
724             else
725             {
726                 while (k<i)
727                 {
728                    if (hybrid_r)
729                     {
730                         if (hybrid_r==2) fprintf(dotc,macro[H2_STEP],k,k,m,m);
731                         if (hybrid_r==4) fprintf(dotc,macro[H4_STEP],k,k,k,k,m,m,m,m);
732                     }
733                     else fprintf(dotc,macro[STEP],k,m);
734                     k+=inc; m-=inc;
735                 }
736             }
737 
738             if (hybrid_r)
739             {
740                 if (hybrid_r==2) fprintf(dotc,macro[H2_RFINU],n,n,n,n);
741                 if (hybrid_r==4) fprintf(dotc,macro[H4_RFINU],n,n,n,n,n,n,n,n);
742             }
743             else fprintf(dotc,macro[RFINU],n,n);
744         }
745 
746         for (i=0;i<PARAM-inc;i+=inc,n+=inc)
747         {
748             k=i+inc; m=PARAM-inc;
749 
750             if (scheduled)
751             {
752                 x=1;
753                 m_prologue(dotc,k,m);
754                 k++; m--;
755 
756                 while (k<=PARAM-1)
757                 {
758                     m_schedule(dotc,x,k,m);
759                     k++; m--;
760                     x=3-x;
761                 }
762                 m_epilogue(dotc,x);
763             }
764             else
765             {
766                while (k<=PARAM-inc)
767                 {
768                     if (hybrid_r)
769                     {
770                         if (hybrid_r==2) fprintf(dotc,macro[H2_STEP],k,k,m,m);
771                         if (hybrid_r==4) fprintf(dotc,macro[H4_STEP],k,k,k,k,m,m,m,m);
772                     }
773                     else fprintf(dotc,macro[STEP],k,m);
774                     k+=inc; m-=inc;
775                 }
776             }
777 
778             if (hybrid_r)
779             {
780                 if (hybrid_r==2) fprintf(dotc,macro[H2_RFIND],n,n,n,n);
781                 if (hybrid_r==4) fprintf(dotc,macro[H4_RFIND],n,n,n,n,n,n,n,n);
782             }
783             else fprintf(dotc,macro[RFIND],n,n);
784         }
785         if (hybrid_r)
786         {
787             if (hybrid_r==2) fprintf(dotc,macro[H2_REDC_END],2*PARAM-inc,2*PARAM-inc,2*PARAM-inc);
788             if (hybrid_r==4) fprintf(dotc,macro[H4_REDC_END],2*PARAM-inc,2*PARAM-inc,2*PARAM-inc,2*PARAM-inc,2*PARAM-inc);
789         }
790         else fprintf(dotc,macro[REDC_END],2*PARAM-1,2*PARAM-1);
791 
792         break;
793 
794     case ADDITION:
795         fprintf(dotc,macro[ADD_START]);
796         for (i=1;i<PARAM;i++)
797             fprintf(dotc,macro[ADD],i,i,i);
798         fprintf(dotc,macro[ADD_END]);
799         break;
800     case ADDITION2:
801         fprintf(dotc,macro[ADD_START]);
802         for (i=1;i<2*PARAM;i++)
803             fprintf(dotc,macro[ADD],i,i,i);
804         fprintf(dotc,macro[ADD_END]);
805         break;
806     case INCREMENT:
807         fprintf(dotc,macro[INC_START]);
808         for (i=1;i<PARAM;i++)
809             fprintf(dotc,macro[INC],i,i,i);
810         fprintf(dotc,macro[INC_END]);
811         break;
812     case DOUBLEIT:
813         if (macro[DOUBLE_START]!=NULL)
814         {
815             fprintf(dotc,macro[DOUBLE_START]);
816             for (i=1;i<PARAM;i++)
817                 fprintf(dotc,macro[DOUBLE],i,i);
818             fprintf(dotc,macro[DOUBLE_END]);
819         }
820         else
821         {
822             fprintf(dotc,macro[INC_START]);
823             for (i=1;i<PARAM;i++)
824                 fprintf(dotc,macro[INC],i,i,i);
825             fprintf(dotc,macro[INC_END]);
826         }
827         break;
828 
829     case SUBTRACTION:
830         fprintf(dotc,macro[SUB_START]);
831         for (i=1;i<PARAM;i++)
832             fprintf(dotc,macro[SUB],i,i,i);
833         fprintf(dotc,macro[SUB_END]);
834         break;
835     case SUBTRACTION2:
836         fprintf(dotc,macro[SUB_START]);
837         for (i=1;i<2*PARAM;i++)
838             fprintf(dotc,macro[SUB],i,i,i);
839         fprintf(dotc,macro[SUB_END]);
840         break;
841     case DECREMENT:
842         fprintf(dotc,macro[DEC_START]);
843         for (i=1;i<PARAM;i++)
844             fprintf(dotc,macro[DEC],i,i,i);
845         fprintf(dotc,macro[DEC_END]);
846         break;
847     case SUMMATION:
848         fprintf(dotc,macro[KADD_START],1);
849         for (i=0;i<PARAM;i++)
850             fprintf(dotc,macro[ADD],i,i,i);
851         fprintf(dotc,macro[KASL],2,PARAM,PARAM,PARAM,1,2);
852         fprintf(dotc,macro[KADD_END]);
853         break;
854     case INCREMENTATION:
855         fprintf(dotc,macro[KINC_START],3);
856         for (i=0;i<PARAM;i++)
857             fprintf(dotc,macro[INC],i,i,i);
858         fprintf(dotc,macro[KIDL],4,PARAM,PARAM,3,4);
859         fprintf(dotc,macro[KINC_END]);
860         break;
861     case DECREMENTATION:
862         fprintf(dotc,macro[KDEC_START],5);
863         for (i=0;i<PARAM;i++)
864             fprintf(dotc,macro[DEC],i,i,i);
865         fprintf(dotc,macro[KIDL],6,PARAM,PARAM,5,6);
866         fprintf(dotc,macro[KDEC_END]);
867         break;
868     default:
869         break;
870     }
871 }
872 
main(int argc,char ** argv)873 int main(int argc,char **argv)
874 {
875     FILE *templat,*macros,*dotc;
876     int i,ip,ptr,index,size;
877     BOOL open,error;
878     char fname[80],tmpl[80],name[20];
879     char line[133];
880     argc--; argv++;
881     if (argc<3 || argc>4)
882     {
883        printf("Bad arguments\n");
884        printf("mex <parameter> <.mcs file> <.tpl file>\n");
885        printf("Use flag -s for scheduled code\n");
886        printf("Examples:\n");
887        printf("mex 6 ms86 mrcomba\n");
888        printf("mex -s 8 c mrkcm\n");
889        exit(0);
890     }
891     ip=0;
892     scheduled=FALSE;
893     if (strcmp(argv[0],"-s")==0)
894     {
895         ip=1;
896         scheduled=TRUE;
897     }
898 
899     PARAM=atoi(argv[ip]);
900     if (PARAM<2 || PARAM>40)
901     {
902         printf("Invalid parameter\n");
903         exit(0);
904     }
905     strcpy(fname,argv[ip+1]);
906     strcat(fname,".mcs");
907     macros=fopen(fname,"rt");
908     if (macros==NULL)
909     {
910         printf("Macro file %s not found\n",fname);
911         exit(0);
912     }
913 
914     strcpy(tmpl,argv[ip+2]);
915     strcat(tmpl,".tpl");
916     templat=fopen(tmpl,"rt");
917     if (templat==NULL)
918     {
919         printf("Template file %s file not found\n",tmpl);
920         exit(0);
921     }
922     strcpy(tmpl,argv[ip+2]);
923     strcat(tmpl,".c");
924     dotc=fopen(tmpl,"wt");
925     if (dotc==NULL)
926     {
927         printf("Unable to open %s for output\n",tmpl);
928         exit(0);
929     }
930 
931     for (i=0;i<LAST_ONE;i++) macro[i]=NULL;
932 
933 /* read in the macros - first pass to determine size and check for errors */
934     open=error=FALSE;
935     while (1)
936     {
937         if (fgets(line,132,macros)==NULL) break;
938         if (line[0]==';') continue;
939 
940         if (!open && strncmp(line,"MACRO",5)==0)
941         {
942                 open=TRUE;
943                 ptr=6; i=0;
944                 ptr=skip(line,ptr);
945                 while (!white(line[ptr])) name[i++]=line[ptr++];
946                 name[i]='\0';
947                 index=which(name,names);
948                 if (index<0)
949                 {
950                     error=TRUE;
951                     break;
952                 }
953                 size=0;
954                 continue;
955         }
956         if (open && strncmp(line,"ENDM",4)==0)
957         {
958                 open=FALSE;
959                 macro[index]=(char *)malloc(size+1);
960                 macro[index][0]='\0';
961         }
962 
963         if (open) size+=(int)strlen(line);
964     }
965     fclose(macros);
966     if (error)
967     {
968         printf("no such macro - %s\n",name);
969         exit(0);
970     }
971 
972 /* read in the macros - second pass to store macros */
973     macros=fopen(fname,"rt");
974     while (1)
975     {
976         if (fgets(line,132,macros)==NULL) break;
977         if (line[0]==';') continue;
978 
979         if (!open && strncmp(line,"MACRO",5)==0)
980         {
981                 open=TRUE;
982                 ptr=6; i=0;
983                 ptr=skip(line,ptr);
984                 while (!white(line[ptr])) name[i++]=line[ptr++];
985                 name[i]='\0';
986                 index=which(name,names);
987                 continue;
988         }
989         if (open && strncmp(line,"ENDM",4)==0) open=FALSE;
990 
991         if (open) strcat(macro[index],line);
992     }
993     fclose(macros);
994 
995     if (macro[PMUL]==NULL)
996     {
997        /* printf("Pseudo Mersenne Primes not (yet) supported for this architecture in file %s\n",fname); */
998         pmp=0;
999     }
1000     else pmp=1;
1001 
1002     if (scheduled && macro[STEP1M]==NULL)
1003     {
1004         printf("Error - scheduling not supported in file %s\n",fname);
1005         exit(0);
1006     }
1007     hybrid=0;
1008     if (macro[H2_STEP]!=NULL) hybrid=2;
1009     if (macro[H4_STEP]!=NULL) hybrid=4;
1010 
1011     hybrid_b=0;
1012     if (macro[H2_STEPB]!=NULL) hybrid_b=2;
1013     if (macro[H4_STEPB]!=NULL) hybrid_b=4;
1014 
1015     hybrid_r=0;
1016     if (macro[H2_RFINU]!=NULL) hybrid_r=2;
1017     if (macro[H4_RFINU]!=NULL) hybrid_r=4;
1018 
1019     if (hybrid)
1020     {
1021         printf("Found hybrid macros - max step size = %d\n",hybrid);
1022         if (PARAM%hybrid!=0)
1023         {
1024             printf("Warning - %d should be a multiple of %d for hybrid method\n",PARAM,hybrid);
1025             hybrid=0;
1026         }
1027     }
1028 
1029     if (hybrid_b)
1030     {
1031         printf("Found hybrid macros for binary case - max step size = %d\n",hybrid_b);
1032         if (PARAM%hybrid_b!=0)
1033         {
1034             printf("Warning - %d should be a multiple of %d for hybrid method\n",PARAM,hybrid_b);
1035             hybrid_b=0;
1036         }
1037     }
1038 
1039     if ((scheduled && hybrid) || (scheduled && hybrid_b))
1040     {
1041         printf("Error - scheduling not supported in file %s\n",fname);
1042         exit(0);
1043     }
1044 
1045 /* Insert macros into dotc file */
1046 
1047     while (1)
1048     {
1049         if (fgets(line,132,templat)==NULL) break;
1050         fputs(line,dotc);
1051         if (strncmp(line,"/***",4)==0)
1052         {
1053                 ptr=4; i=0;
1054                 ptr=skip(line,ptr);
1055                 while (!white(line[ptr])) name[i++]=line[ptr++];
1056                 name[i]='\0';
1057 
1058                 index=which(name,functions);
1059               /*  printf("Recognize %s index %d\n",name,index);  */
1060                 if (index<0)
1061                 {
1062                     error=TRUE;
1063                     break;
1064                 }
1065                 insert(index,dotc);
1066         }
1067     }
1068 
1069     if (error)
1070         printf("no such function - %s\n",name);
1071 
1072     fclose(templat);
1073     fclose(dotc);
1074     return 0;
1075 }
1076 
1077