1#!/bin/ch
2/* For creating Ch Ming 1.0, Feb 10, 2006
3
4    this script does the following:
5    + Copies headers from <MING_HOME>/src/include to ./chming/include subfolder
6    + Copies Ming DLLs to ./chming/bin subfolders
7    + Copies C/Ch samples from ./demos/ directory to ./chming/demos
8    + Generates *.h files in ./chfcreate/ directory, those files contain a
9      list of function prototypes for Ming. This list is based off of ming.h.
10    + Processes each function list with c2chf
11    + Moves *.chf files generated by c2chf to ./chming/lib subfolder and
12      *_chdl.c files to ./c subfolder
13    + Builds .dl files using Ch SDK and places them to ./chming/dl
14*/
15
16#include <unistd.h>   // for access()
17#include <dlfcn.h>    // for dlopen()
18#include <chshell.h>  // for chinfo()
19
20int addChdlHeader(char *headerfile, char *macro, char *chdlheader);
21int removeFuncProto(char *filename, char *funcname, int keepNum);
22int changeChfFiles(char *IncDir, char *LibDir);
23
24string_t pkgname="chming";      // define package name
25chinfo_t info;                  // for Ch version number
26string_t cwd = _cwd;            // the current working directory
27string_t lib_header_dir;        // library header files directory
28string_t debugFile;             // compilation debug information in Windows
29string_t debug;
30string_t makecmd;
31int i;
32#if defined(_WIN32_)
33    debug=">nul 2>nul";         // surpress messages during cleaning  in Windows
34    debugFile =">logfile 2>&1"; // compilation debug information in 'logfile'
35    makecmd = "nmake -f Makefile.win";
36#else
37    makecmd = "make -f Makefile";
38#endif
39
40
41//make sure pgkcreate.ch is run from the current working directory
42if(access("pkgcreate.ch", R_OK)) {
43    echo Run ./pkgcreate.ch in the current directory.
44    exit(-1);
45}
46// run this script in proper Ch version
47chinfo(&info);
48if ((info.vermajor*100+ info.verminor*10 +  info.vermicro) < 501) {
49   echo "To run this script, you need to install Ch version 5.0.1.12201 or higher"
50   echo "You can download the latest version from http://www.softintegration.com/download"
51   exit(-1);
52}
53
54
55echo Cleaning up existing directories and create new ones ...
56if (!access(pkgname, F_OK))
57  rm -rf $pkgname
58
59/* create directories */
60echo create $pkgname directories
61mkdir $pkgname
62mkdir $pkgname/dl $pkgname/lib $pkgname/include $pkgname/demos $pkgname/bin
63if(access("chfcreate", R_OK)) {
64   mkdir chfcreate
65}
66
67echo Copying header files ...
68cp -f ../src/ming.h  	       $pkgname/include
69cp -f ../src/ming_config.h     $pkgname/include
70
71// if the original package doesn't have the modiciation for Ch
72if(`grep LOAD_CHDL $pkgname/include/ming.h` == NULL)
73{
74    echo Adding LOAD_CHDL into ming.h ...
75    char *macro ="#define Ming_H";
76    char *chdlheader =
77   "\n\n"
78   "#ifdef _CH_\n"
79   "#pragma package <chming> \n"
80   "#include <chdl.h> \n"
81   "LOAD_CHDL(ming); \n"
82   "#endif \n\n";
83   addChdlHeader(stradd(pkgname, "/include/ming.h"), macro, chdlheader);
84}
85
86echo Copying demo programs ...
87cp -fr demos/*        $pkgname/demos
88chmod 755 $pkgname/demos/*.c*
89if(!access(stradd(pkgname, "/demos/CVS"), R_OK)) {
90   rm -rf $pkgname/demos/CVS
91}
92
93//echo copying DLLs ...
94#if defined(_WIN32_)
95    //if there is dynamical library pkgname
96    cp -f ../bin/*.dll $pkgname/bin/ >nul 2>&1
97#endif
98
99/* ming function does not have a common return type */
100echo Creating a header file containing all functions to export ...
101char *returnTypes[]={"int", "void", "float",
102   "SWFBlock", "SWFMatrix", "SWFInput", "SWFCharacter", "SWFDBLBitmap",
103   "SWFDBLBitmapData", "SWFJpegBitmap", "SWFJpegWithAlpha", "SWFGradient",
104   "SWFFillStyle", "SWFLineStyle", "SWFShape", "SWFMorph", "SWFFont",
105   "SWFText", "SWFBrowserFont", "SWFFontCharacter", "SWFTextField",
106   "SWFSoundStream", "SWFSound", "SWFSoundInstance", "SWFCXform", "SWFAction",
107   "SWFButton", "SWFSprite", "SWFPosition", "SWFDisplayItem", "SWFFill",
108   "SWFMovieClip", "SWFMovie", "SWFVideoStream", NULL};
109
110char *fileName;
111rm -rf ./chfcreate/ming.h
112
113for(i=0;returnTypes[i]!=NULL;i++)
114{
115
116   fileName = stradd("chfcreate/", returnTypes[i], ".h");
117   processhfile(returnTypes[i], 1, ";", stradd(pkgname, "/include/ming.h"),
118      fileName, NULL);
119   cat $fileName >> ./chfcreate/ming.h
120   rm -rf $fileName
121}
122
123
124echo Removing duplicates in ming.h ...
125removeFuncProto("chfcreate/ming.h", "SWFSoundInstance_setNoMultiple", 1);
126
127echo Removing special function prototypes in ming.h ...
128/* depreceated */
129removeFuncProto("chfcreate/ming.h", "SWFMovie_outputC", 0);
130/* have pointer to function*/
131removeFuncProto("chfcreate/ming.h", "Ming_setWarnFunction", 0);
132removeFuncProto("chfcreate/ming.h", "Ming_setErrorFunction", 0);
133removeFuncProto("chfcreate/ming.h", "SWFMovie_output", 0);
134
135echo Generating ming_chdl.c in c/ directory and xxx.chf in $pkgname/lib ...
136c2chf chfcreate/ming.h -o c c -o chf $pkgname/lib
137
138echo Patching special .chf files ...
139cp -f chfhandmade/*.chf $pkgname/lib
140chmod 644 $pkgname/lib/*.chf
141
142echo Patching .chf files that return pointer to structure ...
143changeChfFiles("../src", stradd(pkgname, "/lib"));
144
145echo Building the dynamically loaded library ...
146cd c
147$makecmd clean $debug
148$makecmd $debugFile
149
150// go back to original directory
151cd $cwd
152
153echo Adding .DLL path and testing .dl file ...
154#pragma exec _path=stradd(_path, "chming/bin");
155if (dlopen("c/libming.dl", RTLD_LAZY) == NULL) {
156    printf("Error: test of loading libming.dl: %s\n", dlerror());
157    exit(-1);
158}
159
160mv -f c/libming.dl "$cwd/$pkgname/dl"
161
162echo package $pkgname created successfully!
163
164
165/*******************************************************************
166 * * This function will add the required preprocessing directives
167 * * needed by Ch to a header file.
168 * * headerfile:   header file to be changed
169 * * macro:        token to be recoganized for insertion of chdlheader
170 * * chdlheader:   preprocessing directives to be inserted
171 * *******************************************************************/
172int addChdlHeader(char *headerfile, char *macro, char *chdlheader)
173{
174   char *stop_ptr;
175   string_t tempfile, token;
176   string_t result;
177   FILE *stream;
178
179   tempfile = ``cat $headerfile``;
180   token = strstr( tempfile, macro);
181   stop_ptr = strstr(token, "\n");
182   strncpy(result, tempfile, strlen(tempfile)-strlen(stop_ptr));
183   result=stradd(result, chdlheader);
184   result=stradd(result, stop_ptr);
185   if(!(stream = fopen("_tmpfile", "w")))
186   {
187      perror("_tmpfile");
188      return -1;
189   }
190   fprintf(stream, "%s", result);
191   fclose(stream);
192   mv -f _tmpfile $(headerfile)
193   return 0;
194}
195
196
197/*************************************************************************
198 * (C) Copyright 2005 SoftIntegration, Inc.
199 * This function is in public domain, use as it is without any warranty.
200 **************************************************************************
201 * This function removes function prototypes such as
202 *     int func1(int i);
203 * from a header file that has already been filtered through processhfile().
204 *
205 * Argumnets:
206 *    filename: name of the file to process
207 *    funcname: function name to look for
208 *    keepNum: if 0, remove all occurances of this prototype.
209 *             if >0 , keep the keepNum desired funcname that is found.
210 * Example:
211 *    removeFuncProto("chfcreate/test.h", "func1", 2);
212 * This will remove all instances except for the 2nd instance of the function,
213 * func1(), prototype that is found in the file chfcreate/test.h.
214 ***************************************************************/
215#define LINESIZE 1024
216int removeFuncProto(char *filename, char *funcname, int keepNum)
217{
218   char line[LINESIZE], *ptr;
219   string_t filenameout;
220   FILE *stream1, *stream2;
221   int num = 0;
222
223   /* Check to see if the funcname provided is NULL */
224   if (funcname == NULL)
225   {
226      printf("Error: %s: Null funcname recieved.\n", __func__);
227      return -1;
228   }
229
230   /* Check for access to the file */
231   if(!(stream1 = fopen(filename, "r")))
232   {
233      printf("Error: %s: Unable to open '%s' for reading.\n", __func__, filename);
234      return -1;
235   }
236
237   filenameout = tmpnam(NULL);
238   /* Check for access to the file */
239   if(!(stream2 = fopen(filenameout, "w")))
240   {
241      printf("Error: %s: Unable to open '%s' for writing.\n", __func__, filenameout);
242      return -1;
243   }
244
245    fgets(line, LINESIZE , stream1);
246    while(!feof(stream1)) {
247        if(ptr = strstr(line, funcname)) {
248           if(*(ptr-1) == ' ' || *(ptr-1) == '\t' || /* find ' ' in "int' 'funcname();" */
249              *(ptr-1) == '*')     /* find * in "int *funcname();" */
250           {
251              ptr += strlen(funcname);
252              while(*ptr == ' ')         /* skip ' ' in "int funcname' '();" */
253              {
254                 ptr++;
255              }
256              if(*ptr == '(') {          /* Find '(' in "int funcname();" */
257                 num++;
258                 if(num != keepNum) {
259                   while(!strchr(line, ';'))      /* till find ';' in "int funcname();" */
260                   {
261                     fgets(line, LINESIZE , stream1);
262                   }
263                   fgets(line, LINESIZE , stream1);
264                   continue;
265                 }
266              }
267           }
268        }
269        fputs(line, stream2);
270        fgets(line, LINESIZE , stream1);
271    }
272    fclose(stream1);
273    fclose(stream2);
274   /* Move the temperary file to the original file. */
275    mv -f $filenameout $filename
276    return 0;
277}
278
279/*******************************************************************
280* This function will change the chf files so that they return
281* a NULL instead of a -1 when a pointer to structure is returned by the
282* function.
283* The list of known structures are normally provided in the ming.h
284* header file.
285*
286* IncDir: Directory where ming.h is located
287* LibDir: Directory where the chf files should be modified
288*******************************************************************/
289int changeChfFiles(char *IncDir, char *LibDir)
290{
291   string_t structList;
292   string_t tempStructList;
293   string_t tempStr;
294   string_t chfList;
295   string_t chfFile;
296   string_t output;
297   string_t workingDir;
298   char *chfFileName;
299   char *tempChrPtr;
300   char *test;
301   char *startChrPtr;
302   char *endChrPtr;
303   char *macro = "return -1;";
304   char *mingHeaderLocation = stradd(IncDir, "/ming.h");
305   FILE *fptr;
306
307   workingDir = _cwd;
308
309   if(access(mingHeaderLocation, R_OK))
310   {
311       printf("Error: Unable to find '%s'.\n"
312              "Chf files will not be modified.\n",
313              mingHeaderLocation);
314       return -1;
315   }
316
317   if(access(LibDir, R_OK))
318   {
319       printf("Error: Unable to find '%s'.\n"
320              "Chf files will not be modified.\n",
321              LibDir);
322       return -1;
323   }
324
325   tempStructList = `grep "typedef struct" $mingHeaderLocation`;
326
327   foreach(tempChrPtr; tempStructList; NULL; ";")
328   {
329
330       if( (tempChrPtr = strstr(tempChrPtr, "*")) == NULL)
331       {
332           continue;
333       }
334
335       tempChrPtr += 1;
336       endChrPtr = strstr(tempChrPtr, ";");
337
338       strncpy(tempStr, tempChrPtr, strlen(tempChrPtr)-strlen(endChrPtr));
339       structList = stradd(structList, tempStr, " ");
340   }
341
342#ifdef DEBUG
343   printf("%s\n", structList);
344#endif
345
346   cd $LibDir
347
348#ifdef DEBUG
349   printf("\tModifying Chf Files...\n");
350#endif
351
352   foreach(tempChrPtr; structList; NULL; " ")
353   {
354       test = stradd(tempChrPtr, " retval");
355       chfList = `grep -l "$test" *.chf`;
356
357#ifdef DEBUG
358       printf("looking for %s\n", tempChrPtr);
359       printf("%s\n", chfList);
360#endif
361
362       foreach(chfFileName; chfList; NULL; " ")
363       {
364
365#ifdef DEBUG
366           printf("testing file %s\n", chfFileName);
367#endif
368
369           chfFile = ``cat $chfFileName``;
370
371           if( (startChrPtr = strstr(chfFile, macro)) == NULL)
372           {
373               printf("\t%s not found in %s.\n", macro, chfFileName);
374               continue;
375           }
376
377           strncpy(output, chfFile, strlen(chfFile)-strlen(startChrPtr));
378           startChrPtr += strlen(macro);
379           output = stradd(output, "return NULL;", startChrPtr);
380
381           fptr = fopen("temp12345.txt", "w");
382           fprintf(fptr, "%s", output);
383           fclose(fptr);
384           mv -f temp12345.txt $chfFileName
385       }
386   }
387
388   cd $workingDir
389
390   return 0;
391}
392