// -*- mode:C++ ; compile-command: "g++ -I.. -g -c help.cc -Wall" -*-
//#define _SCL_SECURE_NO_WARNINGS
#include "giacPCH.h"
#include "path.h"
/*
* Copyright (C) 2000,14 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
using namespace std;
#include
#include "gen.h"
#include "help.h"
#include
#include "global.h"
#ifdef HAVE_UNISTD_H
#include
#endif
#if defined VISUALC || defined BESTA_OS
#define opendir FindFirstFile
#define readdir FindNextFile
#define closedir FindClose
#define DIR WIN32_FIND_DATA
#define GNUWINCE 1
#else // VISUALC or BESTA_OS
#ifdef HAVE_SYS_PARAM_H
#include
#endif
#if !defined BESTA_OS && !defined NSPIRE && !defined NUMWORKS // test should always return true
#include
#endif
#endif // VISUALC or BESTA_OS
#include "input_lexer.h"
#ifndef NO_NAMESPACE_GIAC
namespace giac {
#endif // ndef NO_NAMESPACE_GIAC
const int HELP_LANGUAGES=4;
struct static_help_t {
const char * cmd_name;
const char * cmd_howto[HELP_LANGUAGES];
const char * cmd_syntax;
const char * cmd_related;
const char * cmd_examples;
};
const static_help_t static_help[]={
#if !defined RTOS_THREADX && !defined BESTA_OS && !defined GIAC_HAS_STO_38
#include "static_help.h"
#else
{ "", { "", "", "", ""}, "", "", "" },
#endif
};
const int static_help_size=sizeof(static_help)/sizeof(static_help_t);
struct static_help_sort {
static_help_sort() {}
inline bool operator () (const static_help_t & a ,const static_help_t & b){
return strcmp(a.cmd_name, b.cmd_name) < 0;
}
};
inline int mon_max(int a,int b){
if (a>b)
return a;
else
return b;
}
bool seconddec (const pair & a,const pair & b){
return a.second>b.second;
}
// NB: cmd_name may be localized but related is not localized
bool has_static_help(const char * cmd_name,int lang,const char * & howto,const char * & syntax,const char * & related,const char * & examples){
#ifdef GIAC_HAS_STO_38
const char nullstring[]=" ";
#else
const char nullstring[]="";
#endif
if (lang<=0)
lang=2;
if (lang>HELP_LANGUAGES)
lang=2;
string s=unlocalize(cmd_name);
int l=int(s.size());
if ( (l>2) && (s[0]=='\'') && (s[l-1]=='\'') )
s=s.substr(1,l-2);
static_help_t h={s.c_str(),{0,0,0,0},0,0,0};
std::pair p=equal_range(static_help,static_help+static_help_size,h,static_help_sort());
if (p.first!=p.second && p.first!=static_help+static_help_size){
howto=p.first->cmd_howto[lang-1];
if (!howto)
howto=p.first->cmd_howto[1];
syntax=p.first->cmd_syntax;
if (!syntax)
syntax=nullstring;
related=p.first->cmd_related;
if (!related)
related=nullstring;
examples=p.first->cmd_examples;
if (!examples)
examples=nullstring;
return true;
}
#ifdef EMCC
// Find closest string
syntax=nullstring;
related=nullstring;
static string res;
res="";
int best_score=0,cur_score;
vector< pair > best_j;
for (int j=0;jbest_score){
best_score=cur_score;
vector< pair > tmp;
for (unsigned k=0;k=best_score-6)
tmp.push_back(best_j[k]);
}
best_j=tmp;
best_j.push_back(pair(j,cur_score));
continue;
}
if (cur_score>=mon_max(best_score-6,0)){
best_j.push_back(pair(j,cur_score));
}
}
if (best_score>0){
sort(best_j.begin(),best_j.end(),seconddec);
vector< pair >::iterator it=best_j.begin(),itend=best_j.end();
for (int k=1;(k<10) && (it!=itend);++k,++it){
res = res+static_help[it->first].cmd_name;
res = res+",";
}
if (!res.empty())
res=res.substr(0,res.size()-1);
}
static string syn;
syn = gettext("Best match has score ") + printint(best_score) + "\n";
howto = syn.c_str();
examples = res.c_str();
return true;
#else
return false;
#endif
}
static std::string output_quote(const string s){
string res;
int ss=int(s.size());
for (int i=0;i & v,const vector & langv){
#ifndef NSPIRE
ofstream of("static_help.h");
vector::iterator it=v.begin(),itend=v.end();
for (;it!=itend;){
of << "{";
of << '"' << output_quote(it->cmd_name) << '"' << ",";
std::vector & blabla = it->blabla;
sort(blabla.begin(),blabla.end());
int bs=int(blabla.size());
of << "{";
for (int i=0;isyntax) << '"' << ',' ;
std::vector & examples = it->examples;
bs=int(examples.size());
if (bs){
of << '"';
for (int i=0;i & related = it->related;
bs=int(related.size());
if (bs){
of << '"';
for (int i=0;icmd_name;
ofw << 'L' << '"' << output_quote(cmd) << '"' << ",";
if (cmd.size()>16)
cmd=cmd.substr(0,16);
ofwindex << "{NULL,NULL, " << 'L' << '"' << output_quote(cmd) << '"' << ", HIDVoid }" ;
std::vector & blabla = it->blabla;
sort(blabla.begin(),blabla.end());
int bs=int(blabla.size());
ofw << "{";
for (int i=0;icmd_name) << '(' << output_quote(it->syntax) << ')' << '"' << ',' ;
std::vector & examples = it->examples;
bs=int(examples.size());
if (bs>=1){
ofw << 'L' << '"';
ofw << output_quote(examples[0]) ;
ofw << '"' << ',';
if (bs>=2){
ofw << 'L' << '"';
ofw << output_quote(examples[1]) ;
ofw << '"' << ',';
}
else
ofw << 0 << ",";
}
else
ofw << 0 << "," << 0 << ",";
std::vector & related = it->related;
bs=int(related.size());
if (bs>=1){
ofw << 'L' << '"';
ofw << output_quote(related[0].chaine) ;
ofw << '"' << ',';
if (bs>=2){
ofw << 'L' << '"';
ofw << output_quote(related[1].chaine) ;
ofw << '"' << ',';
}
else
ofw << 0 << ",";
}
else
ofw << 0 << "," << 0 << ",";
ofw << "}";
++it;
if (it==itend)
break;
ofw << "," << endl;
ofwindex << "," << endl;
}
ofw << endl;
ofwindex << "};" << endl;
#endif
return true;
}
bool operator < (const indexed_string & is1,const indexed_string & is2){
if (is1.index!=is2.index) return is1.index-1;--length,i/=10)
s[length]=i%10+'0';
#if defined VISUALC || defined BESTA_OS
string res=s;
delete [] s;
return res;
#else
return s;
#endif
}
inline int max(int a,int b,int c){
if (a>=b){
if (a>=c)
return a;
else
return c;
}
if (b>=c)
return b;
else
return c;
}
int score(const string & s,const string & t){
int ls=int(s.size()),lt=int(t.size());
if (!ls) return -1;
vector cur_l, new_l(lt+1,0);
for (int j=0;j<=lt;++j)
cur_l.push_back(-j);
vector::iterator newbeg=new_l.begin(),newend=new_l.end(),newit=newbeg;
vector::iterator curbeg=cur_l.begin(),curit;//curend=cur_l.end(),
for (int i=0;i & current_synonymes){
current_synonymes.clear();
// parse curren_aide.cmd_name for synonyms
string s=cmd_name,s1;
int i;
for (;;){
// cout << s << endl;
i=int(s.find(' '));
if (i<=0){
if (!s.empty())
current_synonymes.push_back(localized_string(0,s));
break;
}
s1=s.substr(0,i);
current_synonymes.push_back(localized_string(0,s1));
/* add also keyword translations of s1
multimap::iterator it=back_lexer_localization_map().find(s1),backend=back_lexer_localization_map().end(),itend=back_lexer_localization_map().upper_bound(s1);
if (it!=backend){
for (;it!=itend;++it){
current_synonymes.push_back(it->second);
}
}
*/
s=s.substr(i+1,s.size()-i-1);
} // end for (;;)
}
vector readhelp(const char * f_name,int & count,bool warn){
vector v(1);
readhelp(v,f_name,count,warn);
return v;
}
// FIXME: aide_cas may end with synonyms (# cmd synonym1 ...)
void readhelp(vector & v,const char * f_name,int & count,bool warn){
count=0;
#ifndef NSPIRE
if (access(f_name,R_OK)){
if (warn)
std::cerr << "Help file " << f_name << " not found" << endl;
return ;
}
// v.reserve(1600);
ifstream f(f_name);
char fs[HELP_MAXLENSIZE+1];
vector current_blabla;
vector current_related;
vector current_examples;
aide current_aide;
vector vposition;
int vpositions;
string current_line;
vector current_synonymes;
while (f){
f.getline(fs,HELP_MAXLENSIZE,'\n');
if (!fs[0])
continue;
current_line=fs;
if (fs[0]=='#'){
current_aide.blabla=current_blabla;
current_aide.examples=current_examples;
current_aide.related=current_related;
if (!current_aide.cmd_name.empty()){
find_synonymes(current_aide.cmd_name,current_synonymes);
current_aide.synonymes=current_synonymes;
vector::const_iterator it=current_synonymes.begin(),itend=current_synonymes.end();
vpositions=int(vposition.size());
for (int pos=0;it!=itend;++it,++pos){
current_aide.cmd_name=it->chaine;
if (pos2?current_line.substr(2,current_line.size()-2):"";
// search if cmd_name is already present in v
// if so set vposition, current_blabla/examples/related accordingly
find_synonymes(current_aide.cmd_name,current_synonymes);
vector::const_iterator itbeg=current_synonymes.begin(),itend=current_synonymes.end(),it;
vector::iterator itpos;
for (it=itbeg;it!=itend;++it){
itpos=lower_bound(v.begin(),v.end(),current_aide,alpha_order);
if (itpos!=v.end()){
// --itpos;
if (itpos->cmd_name==it->chaine){ // already documented
current_synonymes=itpos->synonymes;
current_blabla=itpos->blabla;
current_examples=itpos->examples;
current_related=itpos->related;
vposition.push_back(int(itpos-v.begin()));
}
}
}
continue;
}
// look for space
int l=int(current_line.find_first_of(' '));
if ( (l==1) && (current_line[0]=='0') ){
int cs=int(current_line.size());
while (l'9')){
n=0;
break;
}
else
n=10*n+(current_line[i]-int('0'));
}
if (!positif)
n=-n;
if (n>0)
current_blabla.push_back(localized_string(n,current_line.substr(l+1,current_line.size()-l)));
else {
if (n<0)
current_related.push_back(indexed_string(-n,current_line.substr(l+1,current_line.size()-l)));
else
current_examples.push_back(current_line);
}
} // end reading help from file
if (!current_aide.cmd_name.empty()){
current_aide.synonymes=vector(1,localized_string(0,current_aide.cmd_name));
current_aide.blabla=current_blabla;
current_aide.examples=current_examples;
current_aide.related=current_related;
v.push_back(current_aide);
count++;
}
sort(v.begin(),v.end(),alpha_order);
if (debug_infolevel==-2){
vector langv;
langv.push_back(1);
langv.push_back(2);
// langv.push_back(3);
// langv.push_back(4);
output_static_help(v,langv);
}
#endif
}
static aide add_synonyme_name_to_examples(const aide & a){
aide res(a);
std::vector::iterator it=res.examples.begin(),itend=res.examples.end();
for (;it!=itend;++it){
if (!it->empty() && (*it)[0]==' ')
continue;
// look for a (
unsigned i=unsigned(it->find('('));
if (i>0 && isize()){ // check whether the beginning of the string is in synonyms
string cmd=it->substr(0,i);
std::vector::const_iterator jt=res.synonymes.begin(),jtend=res.synonymes.end();
for (;jt!=jtend;++jt){
if (jt->chaine==cmd)
break;
}
if (jt!=jtend) // Yes, replace it
*it=res.cmd_name+it->substr(i,it->size()-i);
else
*it=res.cmd_name+'('+*it+')';
}
else
*it=res.cmd_name+'('+*it+')';
}
return res;
}
aide helpon(const string & demande,const vector & v,int language,int count,bool with_op){
aide result;
string current(demande);
if (with_op)
result.syntax = gettext("No help available for ") +current +"\n";
else
result.syntax="NULL";
if (!count){
return result;
}
for (int i=1;;++i){
if (i==count){
if (!with_op)
return result;
// Find closest string
int best_score=0,cur_score;
vector< pair > best_j;
for (int j=1;jbest_score){
best_score=cur_score;
vector< pair > tmp;
for (unsigned k=0;k=best_score-6)
tmp.push_back(best_j[k]);
}
best_j=tmp;
best_j.push_back(pair(j,cur_score));
continue;
}
if (cur_score>=mon_max(best_score-6,0)){
best_j.push_back(pair(j,cur_score));
}
}
if (best_score>0){
sort(best_j.begin(),best_j.end(),seconddec);
vector< pair >::iterator it=best_j.begin(),itend=best_j.end();
for (int k=1;(k<10) && (it!=itend);++k,++it)
result.related.push_back(indexed_string(k,v[it->first].cmd_name));
}
result.syntax += gettext("Best match has score ") + printint(best_score) + "\n";
result.cmd_name = current;
return result;
}
if (current==v[i].cmd_name){
result=v[i];
if (!with_op)
return add_synonyme_name_to_examples(result);
result.syntax= current + "(" +result.syntax +")\n";
return add_synonyme_name_to_examples(result);
}
} // end for i
}
string writehelp(const aide & cur_aide,int language){
string result=cur_aide.syntax;
vector::const_iterator it=cur_aide.blabla.begin(),itend=cur_aide.blabla.end();
for (;it!=itend;++it){
if (it->language==language){
result += it->chaine +'\n' ;
break;
}
}
vector::const_iterator iti=cur_aide.related.begin(),itiend=cur_aide.related.end();
if (itiend!=iti){
result += gettext("See also: ");
for (;iti!=itiend;++iti){
result += printint(iti->index) + "/ " + iti->chaine + " ";
}
result += '\n' ;
}
vector::const_iterator its=cur_aide.examples.begin(),itsend=cur_aide.examples.end();
for (int i=1;its!=itsend;++its,++i){
string current = "Ex" + printint(i)+':'+*its ;
result += current +'\n' ;
// system(current.c_str());
}
return result;
}
#if !defined(NSPIRE_NEWLIB) || !defined(RTOS_THREADX) && !defined(EMCC) &&!defined(NSPIRE)
multimap html_mtt,html_mall;
std::vector html_vtt,html_vall;
// WARNING rebuilding caches works with old version of hevea (1.10) but not with hevea 2.29
// find index nodes in file file
static bool find_index(const std::string & current_dir,const std::string & file,multimap&mtt,multimap&mall,bool is_index=false,bool warn=false){
if (access(file.c_str(),R_OK))
return false;
ifstream i(file.c_str());
// Skip navigation panel
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
char * buf=new char[BUFFER_SIZE+1];
#else
char buf[BUFFER_SIZE+1];
#endif
for (;i && !i.eof();){
i.getline(buf,BUFFER_SIZE,'\n');
string s(buf),stmp;
if (s=="") // latex2html?
break;
int t=int(s.size());
if (t>24 && ((stmp=s.substr(t-24,24))=="" || stmp=="")){
// hevea file contains index
for (;i && !i.eof(); ){
i.getline(buf,BUFFER_SIZE,'\n');
s=buf;
t=int(s.size());
if (t>29 && ((stmp=s.substr(0,29))=="" || stmp=="")){
s=s.substr(29,s.size()-29);
t=int(s.size());
if (!t || s[0]=='<') // skip index words with special color/font
continue;
int endcmd=int(s.find("<")); // position of end of commandname
if (endcmd>2 && endcmd hrefs;
for (;;){
t=int(s.size());
endcmd=int(s.find("=t){
endcmd=int(s.find("=t)
break;
}
s=s.substr(endcmd+9,s.size()-endcmd-9);
t=int(s.size());
endcmd=int(s.find("\""));
if (endcmd<0 || endcmd+2>=t)
break;
string link=s.substr(0,endcmd);
if (link[0]=='#')
link = file + link;
else
link = current_dir + link;
s=s.substr(endcmd+2,s.size()-endcmd-2);
t=int(s.size());
if (t<3)
break;
if (s.substr(0,3)=="" || (t>30 && s.substr(0,29)=="::const_iterator it=hrefs.begin(),itend=hrefs.end();
for (;it!=itend;++it){
if (it==hrefs.begin())
mtt.insert(pair(cmdname,*it));
mall.insert(pair(cmdname,*it));
}
} // if (endcmd>2 && endcmd29 &&...
} // for (;i && !i.eof();) end of file
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
return true;
} // end hevea file with index
// latex2html only?
if (t>14 && s.substr(t-14,14)=="Index "){
// look in the corresponding index file instead
int t1=int(s.find("HREF"))+6;
if (t1>=0 && t1> tmp;
int l=int(tmp.size());
string tts;
if (is_index){
if (l<13)
continue;
int tmpl=0;
if (tmp.substr(0,8)=="")
tmpl=8;
if (tmp.substr(0,12)=="")
tmpl=12;
if (!tmpl)
continue;
int l1=int(tmp.find(""));
if (l1<=tmpl || l1>=l)
continue;
tts=tmp.substr(tmpl,l1-tmpl);
}
else {
if (l<2 || tmp.substr(l-2,2)!="4 && tmp.substr(s-4,4)==""){
// no found, truncate tmp to the first found
int l=int(tmp.find(""));
if (l0)
tmp=tmp.substr(0,l);
s=int(tmp.size());
break;
}
if (s>8 && tmp.substr(s-8,8)==""){
// Find backward the first occurence of 0;--l){
if (tmp[l]=='<' && tmp[l+1]=='A')
break;
}
if (l){
tmp=tmp.substr(l,s-l);
s -= l;
}
break;
}
}
// cerr << tmp << endl;
// analysis, search for HREF
int href=int(tmp.find("HREF=\""));
if (href<0 || href+6>=s)
continue;
string hrefs(current_dir);
int hrefend=0;
for (int j=href+6;j(tts,hrefs));
mall.insert(pair(tts,hrefs));
}
else {
// search for TT
int tt=int(tmp.find("")),ttend=tt;
if (tt>=0 && tt+6(tts,hrefs));
mall.insert(pair(tts,hrefs));
tmp=tmp.substr(0,tt)+tmp.substr(ttend,tmp.size()-ttend);
}
// add href for all normal words
s=int(tmp.size());
int j=hrefend+1;
for (;jj && pos(tmpins,hrefs));
}
if (pos==-1){
string tmpins(tmp.substr(j,s-j));
mall.insert(pair(tmpins,hrefs));
break;
}
j=pos+1;
}
} // end else is_index
}
return false;
}
static const string subdir_strings[]={"cascmd","casgeo","casrouge","cassim","castor","tutoriel","casinter","casexo","cascas"};
static const int subdir_taille=sizeof(subdir_strings)/sizeof(string);
static int equalposcomp(const string * tab,const string & s){
int i=int(s.size())-1;
for (;i>=0;--i){
if (s[i]=='/')
break;
}
++i;
string t=s.substr(i,s.size()-i);
i=int(t.size())-1;
for (;i>=0;--i){
if (t[i]=='_')
t=t.substr(0,i);
}
for (i=0;id_name);
// cerr << s << endl;
int t=s.size();
if (s[t-1]=='\\'){
return s!="." && s!="..";
}
if (t<9)
return 0;
if (s[t-1]=='l'){
s=s.substr(0,t-1);
--t;
}
if (t>9)
s=s.substr(t-9,9);
return s=="index.htm";
}
#else
// __APPLE_CC__ == 5666 on Mac OS X 10.6, 5658 on geogebra build system OS X 10.8
// should check __APPLE__ OS X version instead!
#if ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED)&& __MAC_OS_X_VERSION_MAX_ALLOWED< 1080 ) || ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED)&& __IPHONE_OS_VERSION_MAX_ALLOWED< 60100 ) || defined(__OpenBSD__) || ( defined(__FreeBSD_version)&& __FreeBSD_version<800501)
static int dir_select (struct dirent *d){
#else
static int dir_select (const struct dirent *d){
#endif
string s(d->d_name);
if (d->d_type==DT_DIR || equalposcomp(subdir_strings,s)){
return s!="." && s!="..";
}
int t=s.size();
if (t<9)
return 0;
if (s[t-1]=='l'){
s=s.substr(0,t-1);
--t;
}
if (t>9)
s=s.substr(t-9,9);
return s=="index.htm";
}
#endif
#endif // visualc
void find_all_index(const std::string & subdir,multimap & mtt,multimap & mall){
#if defined GNUWINCE || defined __MINGW_H || defined __ANDROID__ || defined EMCC || defined NSPIRE_NEWLIB
return;
#else
// cerr << "HTML help Scanning " << subdir << endl;
DIR *dp;
struct dirent *ep;
dp = opendir (subdir.c_str());
if (dp != NULL){
string s;
int t;
while ( (ep = readdir (dp)) ){
s=ep->d_name;
t=s.size();
if (t>5 && s.substr(t-4,4)=="html")
html_vall.push_back(subdir+s);
}
closedir (dp);
}
struct dirent **eps;
int n;
#if defined APPLE_SMART || defined NO_SCANDIR
n =-1;
#else
n = scandir (subdir.c_str(), &eps, dir_select, alphasort);
#endif
if (n >= 0){
bool index_done=false;
int cnt;
for (cnt = -1; cnt < n; ++cnt){
string s;
if (cnt==-1)
s="index.html";
else
s=eps[cnt]->d_name;
s= subdir+s;
#ifdef WIN32
int t=s.size();
if (s[t-1]=='\\')
find_all_index(s+"/",mtt,mall);
else {
if (!index_done)
index_done=find_index(subdir,s,mtt,mall);
}
#else
unsigned char type=cnt>=0?eps[cnt]->d_type:0;
if (type==DT_DIR || equalposcomp(subdir_strings,s))
find_all_index(s+"/",mtt,mall);
else {
if (!index_done)
index_done=find_index(subdir,s,mtt,mall);
}
#endif
}
}
#endif // GNUWINCE
}
// Return all HTML nodes refered to s in mtt
std::vector html_help(multimap & mtt,const std::string & s){
vector v;
multimap::const_iterator it=mtt.lower_bound(s),itend=mtt.upper_bound(s);
for (;it!=itend;++it){
v.push_back(it->second);
}
return v;
}
string xcasroot_dir(const char * arg){
string xcasroot;
if (getenv("XCAS_ROOT")){
xcasroot=string(getenv("XCAS_ROOT"));
if (xcasroot.empty())
xcasroot="/";
if (xcasroot[xcasroot.size()-1]!='/')
xcasroot+='/';
}
else {
xcasroot=arg;
int xcasroot_size=int(xcasroot.size())-1;
for (;xcasroot_size>=0;--xcasroot_size){
if (xcasroot[xcasroot_size]=='/')
break;
}
if (xcasroot_size>0)
xcasroot=xcasroot.substr(0,xcasroot_size)+"/";
else {
if (access("/usr/bin/xcas",R_OK)==0)
xcasroot="/usr/bin/";
else {
#ifdef __APPLE__
if (access("/Applications/usr/bin/xcas",R_OK)==0)
xcasroot="/Applications/usr/bin";
#else
if (access("/usr/local/bin/xcas",R_OK)==0)
xcasroot="/usr/local/bin/";
#endif
else
xcasroot="./";
}
}
}
// ofstream of("/tmp/xcasroot");
// of << xcasroot << endl;
return xcasroot;
}
// extern int debug_infolevel;
static bool get_index_from_cache(const char * filename, multimap & multi,bool verbose){
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
char * buf = new char[BUFFER_SIZE];
#else
char buf[BUFFER_SIZE];
#endif
ifstream if_mtt(filename);
int n=0;
while (if_mtt && !if_mtt.eof()){
if_mtt.getline(buf,BUFFER_SIZE,char(0xa4)); // was '¤', utf8 not compatible, octal \244
if (!if_mtt || if_mtt.eof()){
if (verbose)
cerr << "// Read " << n << " entries from cache " << filename << endl;
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
return true;
}
string first(buf);
if_mtt.getline(buf,BUFFER_SIZE,char(0xa4));
if (!if_mtt || if_mtt.eof()){
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
return false;
}
multi.insert(pair(first,buf));
if (!(n%100)){ // check every 100 links if link exists
first=buf;
int l=int(first.size()),j;
char ch=0;
for (j=l-1;j>=0;--j){
ch=first[j];
if (ch=='#' || ch=='/')
break;
}
if (j>0 && ch=='#')
first=first.substr(0,j);
if (access(first.c_str(),R_OK)){
multi.clear();
cerr << "Wrong cache! " << filename << endl;
if_mtt.close();
#if !defined RTOS_THREADX && !defined BESTA_OS && !defined FREERTOS
if (unlink(filename)==-1)
cerr << "You don't have write permissions on " << filename <<".\nYou must ask someone who has write permissions to remove " << filename << endl;
else
cerr << "Cache file "<< filename << " has been deleted" << endl;
#endif
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
return false;
}
}
++n;
if_mtt.getline(buf,BUFFER_SIZE,'\n');
}
if (verbose)
cerr << "// Read " << n << " entries from cache " << filename ;
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
return true;
}
static bool get_index_from_cache(const char * filename, vector & multi,bool verbose){
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
char * buf = new char[BUFFER_SIZE];
#else
char buf[BUFFER_SIZE];
#endif
ifstream if_mtt(filename);
int n=0;
while (if_mtt && !if_mtt.eof()){
if_mtt.getline(buf,BUFFER_SIZE,char(0xa4));
if (!if_mtt || if_mtt.eof()){
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
if (verbose)
cerr << "// Read " << n << " entries from cache " << filename << endl;
return true;
}
multi.push_back(buf);
++n;
if_mtt.getline(buf,BUFFER_SIZE,'\n');
}
#if defined VISUALC || defined BESTA_OS || defined FREERTOS
delete [] buf;
#endif
if (verbose)
cerr << "// Read " << n << " entries from cache " << filename ;
return true;
}
string html_help_init(const char * arg,int language,bool verbose,bool force_rebuild){
string xcasroot=xcasroot_dir(arg);
// HTML online help
string html_help_dir=xcasroot+"doc/";
if (access(html_help_dir.c_str(),R_OK)){
#ifdef __APPLE__
if (!access("/Applications/usr/bin/icas",R_OK))
html_help_dir="/Applications/usr/share/giac/doc/";
#else
if (!access("/usr/bin/xcas",R_OK))
html_help_dir="/usr/share/giac/doc/";
#endif
else {
if (!access("/usr/local/bin/xcas",R_OK))
html_help_dir="/usr/local/share/giac/doc/";
}
}
if (access(html_help_dir.c_str(),R_OK) && xcasroot.size()>4 && xcasroot.substr(xcasroot.size()-4,4)=="bin/")
html_help_dir=xcasroot.substr(0,xcasroot.size()-4)+"share/giac/doc/";
if (access(html_help_dir.c_str(),R_OK))
cerr << "Unable to open HTML doc directory " << html_help_dir << endl;
html_help_dir += find_lang_prefix(language);
#ifdef WIN32
string html_help_dir_save=html_help_dir;
html_help_dir +="cascmd_"+find_lang_prefix(giac::language(context0)); // temporary workaround, for win archive copy doc/fr/html_vall to doc/fr/cascmd_fr/html_vall and change path
#endif
html_mtt.clear();
html_mall.clear();
html_vall.clear();
// Get indices from file cache if it exists
if (!force_rebuild && !access((html_help_dir+"html_mtt").c_str(),R_OK) && !access((html_help_dir+"html_mall").c_str(),R_OK) && !access((html_help_dir+"html_vall").c_str(),R_OK)){
if (get_index_from_cache((html_help_dir+"html_mtt").c_str(),html_mtt,verbose)&&
get_index_from_cache((html_help_dir+"html_mall").c_str(),html_mall,verbose)&&
get_index_from_cache((html_help_dir+"html_vall").c_str(),html_vall,verbose) )
return html_help_dir;
}
find_all_index(html_help_dir,html_mtt,html_mall);
#ifdef WIN32
for (unsigned i=0;i::const_iterator it=html_mtt.begin(),itend=html_mtt.end();
for (;it!=itend;++it)
of_mtt << it->first << char(0xa4) << it->second << char(0xa4) << endl;
of_mtt.close();
ofstream of_mall((html_help_dir+"html_mall").c_str());
it=html_mall.begin();itend=html_mall.end();
for (;it!=itend;++it)
of_mall << it->first << char(0xa4) << it->second << char(0xa4) << endl;
of_mall.close();
ofstream of_vall((html_help_dir+"html_vall").c_str());
vector::const_iterator st=html_vall.begin(),stend=html_vall.end();
for (;st!=stend;++st)
of_vall << *st << char(0xa4) << endl;
of_vall.close();
/*
if (debug_infolevel){
vector::const_iterator it=html_vall.begin(),itend=html_vall.end();
for (;it!=itend;++it)
cerr << *it << endl;
}
*/
return html_help_dir;
}
static bool multigrep(FILE * f,const string & s){
int l=int(s.size());
// find spaces
string tmp;
vector vs;
for (int i=0;i='A' && c<='F')
code = code*base + c-'A'+10;
if (c>='a' && c<='f')
code = code*base + c-'a'+10;
if (c>='0' && c<='9')
code = code*base + c-'0';
}
}
else{
switch (code){
case 0xe8: case 0xe9: case 0xea:
c='e';
break;
case 0xe0: case 0xe2:
c='a';
break;
case 0xf4:
c='o';
break;
case 0xf9: case 0xfb:
c='u';
break;
case 0xe7:
c='c';
break;
case 238:
c='i';
break;
}
break;
}
}
}
}
if (c==' '){
if (!tmp.empty()){ // search tmp in vs
unsigned tmpl=unsigned(tmp.size()),tmpvs;
for (int i=0;i='0' && ch<='9')
return true;
if (ch>='a' && ch<='z')
return true;
if (ch>='A' && ch<='Z')
return true;
if (unsigned(ch)>128)
return true;
if (ch=='_' || ch=='.' || ch=='~')
return true;
/*
char * ptr=otherchars;
for (;*ptr;++ptr){
if (ch==*ptr)
return true;
}
*/
return false;
}
std::string unlocalize(const std::string & s){
std::string res,tmp;
int ss=int(s.size());
std::map::const_iterator it,itend=lexer_localization_map().end();
int mode=0; // 1 if inside a string
for (int i=0;;++i){
char ch=s[i];
if (mode){
if (ch=='"'){
if (res.empty() || res[res.size()-1]!='\\')
mode=0;
}
res += ch;
if (i==ss)
break;
continue;
}
if (isecond; // it is -> we must translate to giac
res += tmp;
tmp = "";
if (ch=='"'){
if (res.empty() || res[res.size()-1]!='\\')
mode=1;
}
if (i::const_iterator it0,it,itend,backend=back_lexer_localization_map().end();
for (int i=0;;++i){
char ch=s[i];
if (mode){
if (ch=='"'){
if (res.empty() || res[res.size()-1]!='\\')
mode=0;
}
res += ch;
if (i==ss)
break;
continue;
}
if (isecond.language==language){
tmp = it->second.chaine;
break;
}
}
if (it==itend)
tmp = it0->second.chaine;
}
res += tmp;
tmp = "";
if (ch=='"'){
if (res.empty() || res[res.size()-1]!='\\')
mode=1;
}
if (i