/src/Hsml/SubLang.c
C | 535 lines | 446 code | 70 blank | 19 comment | 86 complexity | 400c1897c437f07f4526c982341b99fb MD5 | raw file
Possible License(s): GPL-2.0
- #include <time.h>
- #if !SCREWS_MODULE
- #include "main.h"
- extern char *b;
- #endif
- #include "Cache.h"
- #include "SubLang.h"
- sublang_t *sublang;
- int nlangs;
- long int filelen=0;
- int donotexec=0;
- char *dip=DIP;
- char *buf=0;
- char *p=0;
- void *resolve_sym(void *handle, const char *symbol)
- {
- void *sym;
-
- if(!(sym = dlsym(handle, symbol)))
- printf("%s\n", dlerror());
- return sym;
- }
- void hsml_init()
- {
- int i,j;
- char *mod_path = getenv("HSML_LANG_MOD");
- char def_mod_path[] = ".";
- char path[1023];
- char *langs[]={"c","perl","python","brainfuck","clisp",0};//,"clisp","ml","ruby","lua","java","csharp",0};
- int bytes;
- char *cwd;
- void **ptr;
-
- if(!mod_path) mod_path = def_mod_path;
-
- sublang = (sublang_t *)calloc(sizeof(langs)/sizeof(char**),sizeof(sublang_t));
-
- for(i=0, j=0; langs[i]; i++)
- {
- if(mod_path[0] != '/')
- {
- bytes = snprintf(path, 1023, "%s/%s/lang_%s.so", cwd = getcwd(NULL, 0), mod_path, langs[i]);
- free(cwd);
- }
- else bytes = snprintf(path, 1023, "%s/lang_%s.so", mod_path, langs[i]);
-
- if(bytes >= 1023){
- continue;
- }
-
- if(!(sublang[j].module = dlopen(path, RTLD_NOW)))
- {printf("%s\n", dlerror()); continue;}
- if(!(sublang[j].lang = resolve_sym(sublang[j].module, "lang"))) continue;
- if(!(sublang[j].file = resolve_sym(sublang[j].module, "file"))) continue;
-
- if(!(sublang[j].init = resolve_sym(sublang[j].module, "init"))) continue;
- if(!(sublang[j].get_path_from_env = resolve_sym(sublang[j].module, "get_path_from_env"))) continue;
- if(!(sublang[j].show_config = resolve_sym(sublang[j].module, "show_config"))) continue;
- if(!(sublang[j].print_begin = resolve_sym(sublang[j].module, "print_begin"))) continue;
-
- if(!(sublang[j].print_end = resolve_sym(sublang[j].module, "print_end"))) continue;
- if(!(sublang[j].print_end_nl = resolve_sym(sublang[j].module, "print_end_nl"))) continue;
- if(!(sublang[j].code_begin = resolve_sym(sublang[j].module, "code_begin"))) continue;
- if(!(sublang[j].code_end = resolve_sym(sublang[j].module, "code_end"))) continue;
- if(!(sublang[j].codevar = resolve_sym(sublang[j].module, "codevar"))) continue;
- if(!(sublang[j].exec = resolve_sym(sublang[j].module, "exec"))) continue;
- if(!(sublang[j].cache_exec = resolve_sym(sublang[j].module, "cache_exec"))) continue;
-
- if(!(ptr = resolve_sym(sublang[j].module, "cache"))) continue;
- *(char *)ptr = cache;
-
- if(!(ptr = resolve_sym(sublang[j].module, "cacherule"))) continue;
- *(char *)ptr = cacherule;
-
- if(!(ptr = resolve_sym(sublang[j].module, "pwd"))) continue;
- *(char **)ptr = pwd;
-
- if(!(ptr = resolve_sym(sublang[j].module, "tmp"))) continue;
- *(char **)ptr = tmp;
-
- if(!(ptr = resolve_sym(sublang[j].module, "cache_output_add"))) continue;
- *ptr = (void *)&cache_output_add;
-
- if(!(ptr = resolve_sym(sublang[j].module, "cache_print"))) continue;
- *ptr = (void *)&cache_print;
-
- if(!(ptr = resolve_sym(sublang[j].module, "cache_exec_add"))) continue;
- *ptr = (void *)&cache_exec_add;
-
- sublang[j].init();
- j++;
- }
- nlangs = j;
- for(i = 0; i < j; i++)
- {
- sublang[i].show_config();
- }
- }
- void show_lang_config()
- {
- int i;
-
- for(i=0; sublang[i], i<=nlangs; i++)
- sublang[i].show_config();
- }
- bool
- isOk(file1,file2)
- char *file1; /* Source File */
- char *file2; /* Binary File */
- {
-
- struct stat f1,f2;
- if (
- stat(file1,&f1) |
- stat(file2,&f2)
- ) return false; /* ErrOccRrd */
- if (f1.st_mtime>f2.st_mtime)
- return false;
- return true;
- }
- void
- subLang_doExec(file,lang)
- char *file;
- int lang;
- {
- // call lang module exec func
- sublang[lang].exec(file, buf, tmp);
-
- /* XXX type another message ;) */
- fprintf(stderr,"Error executing script. Check language environs with '-l\n");
- sublang[lang].show_config();
- perror("PERROR MSG: ");
- }
- /* TODO : tokenizeBUffer doesn't cleans all params */
- char *
- tokenizeBuffer(buf)
- char *buf;
- {
- // XXX must strdup, etc. tokenizeBuffer, return malloqed buffer
- char *p=buf;
- /* Clear $, etc.. */
- while(1)
- {
- p=strchr(p,'\"');
- if (!p) break;
- p[0]='\'';
- }
- return buf;
- }
- int
- SubLang_include(files,lang)
- char *files;
- int lang;
- {
- FILE *fd;
- char *next, *tmpbuf, *end = p+3, *old_b;
- int b_dif;
- long flen;
- int i=0;
-
- if(files[0] == ' ') files++;
- while(next = strchr(files,' '))
- {
- next[0] = '\0';
- next++;
-
- while(sublang[i].file)
- {
- if (strstr(files,sublang[i].file))
- break;
- i++;
- }
- if (sublang[i].file)
- {
- if (i!=lang)
- {
- sublang[i].print_begin(buf);
- strcat(buf,
- "<font color='red'>"
- "WARNING: Cannot include files written in other language"
- "</font>\n");
- sublang[i].print_end(buf);
- continue;
- }
- }
-
- fd=fopen(files,"r");
- if(fd) {
- fseek(fd,0,SEEK_END);
- flen = ftell(fd);
- fseek(fd,0,SEEK_SET);
- filelen += flen;
- old_b = b;
- b = (char *)realloc(b,filelen+1);
- b_dif = b-old_b;
- p += b_dif;
- next += b_dif;
- end += b_dif;
- tmpbuf = strdup(end);
- fread(end,flen,1,fd);
- end = end+flen;
- strcpy(end,tmpbuf);
- free(tmpbuf);
- fclose(fd);
- } else {
- sublang[i].print_begin(buf);
- strcat(buf,"Cannot include file '");
- strcat(buf,files);
- strcat(buf,"'");
- sublang[i].print_end(buf);
- }
- files = next;
- }
- return 1;
- }
- void
- execSubLang(file,fd,lang,len)
- char *file;
- FILE *fd;
- int lang;
- long int len;
- {
- int i=0;
- int code=0;
- int codevar=0;
- FILE *fdi;
- long flen;
- bool newline=false;
- char *e,*e2,*c,*p2;
- char *include;
- char *tmpbuf;
- char *exe;
-
- filelen=len;
- /* Allocate */
- buf=(char *)malloc(filelen*2+10+len);
- buf[0]='\0';
- /* Concat include file */
- include=malloc(strlen(dip)+20);
- sprintf(include,"%s/include%s",dip,sublang[lang]);
- fdi=fopen(include,"r");
- if (fdi)
- {
- fseek(fd,0,SEEK_END);
- flen=ftell(fd);
- fseek(fd,0,SEEK_SET);
- /* Realocate */
- buf=(char *)realloc(buf,filelen+10+flen);
- fread(buf,len,1,fdi);
- buf[flen]=0;
- fclose(fdi);
- }
- /** BEGIN OF DOCUMENT */
- sublang[lang].code_begin(buf);
-
- /** PARSE THE TAGS */
- filelen=len;
- p=b;
- while(p<b+filelen)
- {
- e=strchr(p,'\n');
- if (e) {
- newline=true;
- e[0]='\0'; /* EOS */
- } else {
- e=strchr(p,'\0');
- }
- if (!code)
- {
- c=strstr(p,"<?");
- codevar=0;
- } else {
- c=strstr(p,"?>");
- if (c) /* tag found in this line. continue and disable code */
- {
- c[0]=0;
- strcat(buf,p);
- p=c+2;
- code=0;
- continue;
- }
- }
-
- if (c)
- {
- c[0]='\0';
- /** Tags */
- switch(c[2])
- {
- case '-': // comment
- p=strstr(c+2,"-?>");
- if (!p)
- {
- sublang[lang].print_begin(buf);
- strcat(buf,"comment tag not closed");
- sublang[lang].print_end(buf);
- goto END_EXEC_SUBLANG;
- }
- p=p+2;
- continue;
- case '^': // header
- p=strstr(c+2,"?>");
- if (!p)
- {
- sublang[lang].print_begin(buf);
- strcat(buf,"tag not closed");
- sublang[lang].print_end(buf);
- goto END_EXEC_SUBLANG;
- }
- p[0]=0;
- p+=2;
- addHeader(c+3);
- continue;
- case '=': // printvar
- codevar=1;
- newline=false;
- break;
- case '%': // directives
- p=strstr(c+2,"?>");
- if (!p)
- {
- sublang[lang].print_begin(buf);
- strcat(buf,"tag not closed");
- sublang[lang].print_end(buf);
- goto END_EXEC_SUBLANG;
- }
- p[0]=0;
- p+=2;
-
- if(e = strstr(c+3, "cacherule="))
- {
- if(!strncmp(e+10, "never", 5)) cacherule = CACHERULE_NEVER;
- else if(!strncmp(e+10, "noinput", 7) && cacherule) cacherule = CACHERULE_NOINPUT;
- else if(!strncmp(e+10, "time", 4) && cacherule) cacherule = CACHERULE_TIME;
- }
- /* TODO parse hsml directives */
- //printf("HSML directives(%s)\n",c+3);
- continue;
- case '&': // include
- p=strstr(c+2,"?>");
- if (!p)
- {
- sublang[lang].print_begin(buf);
- strcat(buf,"tag not closed");
- sublang[lang].print_end(buf);
- goto END_EXEC_SUBLANG;
- }
- p[0]='\0';
- SubLang_include(c+3,lang);
- p+=2;
- continue;
- case '@': // include at top
- p=strstr(c+2,"?>");
- if (!p)
- {
- sublang[lang].print_begin(buf);
- strcat(buf,"tag not closed");
- sublang[lang].print_end(buf);
- goto END_EXEC_SUBLANG;
- }
- p[0]=0;
- tmpbuf=strdup(buf);
- buf=(char *)realloc(buf,filelen+strlen(c+3));
- strcpy(buf,c+3);
- strcat(buf,tmpbuf);
- free(tmpbuf);
- p=p+3;
- continue;
- default:
- if (code)
- strcat(buf,p);
- break;
- }
- }
- if (!code||!newline)
- {
- p2=tokenizeBuffer(p);
- if (strlen(p2))
- {
- sublang[lang].print_begin(buf);
- strcat(buf,p2);
- if (newline) sublang[lang].print_end(buf);
- else sublang[lang].print_end_nl(buf);
- }
- }
- if (c)
- {
- code = !code;
- p=c+2;
- c=strstr(p,"?>");
- if (c) { c[0]='\0'; c++;}
- }
- if (code)
- {
- if (codevar)
- {
- sublang[lang].codevar(buf, p);
- } else {
- strcat(buf,p);
- strcat(buf,"\n");
- }
- if (c)
- {
- code=0;
- e=c;
- }
- }
- if (e) p=e+1;
- else p=c+1;
- }
- END_EXEC_SUBLANG:
-
- if(cache_should_output(file))
- {
- printHeaders();
- cache_print(file);
- return;
- }
- if(cache_should_exec(file))
- {
- printHeaders();
- cache_exec(file, lang);
- return;
- }
-
- if (p) strcat(buf,p);
-
- /** ENDOF DOCUMENT */
- sublang[lang].code_end(buf);
-
- /* Headers */
- printHeaders();
- /* Body */
- if (donotexec)
- printf("%s",buf);
- else
- subLang_doExec(file,lang);
- //free(buf);
- }
- bool
- subLang(file,len)
- char *file;
- long int len;
- {
- int lang=0;
- char buf[1024];
- char *token;
- FILE *fd;
- fd = fopen(file,"r");
- if ( fd == NULL )
- {
- fprintf(stderr,"subLang(%s,%d): cannot open file\n",file,len);
- return false;
- }
-
- if (strstr(file,".hsml"))
- {
- fgets(buf,1000,fd);
- if (!strncmp(buf,"#!",2))
- {
- buf[strlen(buf)-1]=0;
- while(sublang[lang].lang &&
- strcmp(sublang[lang].lang,buf+2))
- { lang++; }
- /* language not found */
- if (!sublang[lang].lang)
- {
- printf("Language hashbang '%s' not found!\n",buf+2);
- fclose(fd);
- return true;
- }
- b=b+strlen(buf)+1;
- len-=strlen(buf)+1;
- } else {
- fclose(fd);
- return false;
- }
- } else {
- while(sublang[lang].file)
- {
- if (strstr(file,sublang[lang].file))
- break;
- lang++;
- }
- }
- if (sublang[lang].file)
- {
- while(token=strchr(file,'/')) // Strip path access
- file = token+1;
- //getPathFromEnv();
- execSubLang(file,fd,lang,len);
- fclose(fd);
- return true; // Found
- }
- return false;
- }