/**************************************************************************** ** *F SySetInitialGapRootPaths( <string> ) . . . . . set the root directories ** ** Set up GAP's initial root paths, based on the location of the ** GAP executable. */ static void SySetInitialGapRootPaths(void) { if (GAPExecLocation[0] != 0) { // GAPExecLocation might be a subdirectory of GAP root, // so we will go and search for the true GAP root. // We try stepping back up to two levels. char pathbuf[GAP_PATH_MAX]; char initgbuf[GAP_PATH_MAX]; strxcpy(pathbuf, GAPExecLocation, sizeof(pathbuf)); for (Int i = 0; i < 3; ++i) { strxcpy(initgbuf, pathbuf, sizeof(initgbuf)); strxcat(initgbuf, "lib/init.g", sizeof(initgbuf)); if (SyIsReadableFile(initgbuf) == 0) { SySetGapRootPath(pathbuf); // escape from loop return; } // try up a directory level strxcat(pathbuf, "../", sizeof(pathbuf)); } } // Set GAP root path to current directory, if we have no other // idea, and for backwards compatibility. // Note that GAPExecLocation must always end with a slash. SySetGapRootPath("./"); }
static Int processCompilerArgs( Char **argv, void * dummy) { SyCompilePlease = 1; strxcat( SyCompileOutput, argv[0], sizeof(SyCompileOutput) ); strxcat( SyCompileInput, argv[1], sizeof(SyCompileInput) ); strxcat( SyCompileName, argv[2], sizeof(SyCompileName) ); SyCompileMagic1 = argv[3]; return 4; }
/** * 功能: Lock implemention based on 'fcntl'. * 参数: @ * 描述: * 1. mkstemp函数在系统中以唯一的文件名创建一个文件并打开,只有一个参数, * 这个参数是个以“XXXXXX”结尾的非空字符串。mkstemp函数会用随机产生的字 * 符串替换“XXXXXX”,保证了文件名的唯一性。 * 2. 临时文件使用完成后应及时删除,否则临时文件目录会塞满垃圾。mkstemp函数 * 创建的临时文件不能自动删除,所以执行完 mkstemp函数后要调用unlink函数, * unlink函数删除文件的目录入口,但临时文件还可以通过文件描述符进行访问, * 直到最后一个打开的进程关 闭文件操作符,或者程序退出后临时文件被自动彻底地删除。 * 返回: 成功, fd。失败,-x **/ int msd_fcntl_init(msd_lock_t **ppl, const char *pathname) { char s[MAXPATHLEN]; int fd; /* 共享内存之上,生成lock。 */ *ppl = mmap(0, sizeof(msd_lock_t), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (*ppl == MAP_FAILED) { fprintf(stderr, "mmap lock failed: %s\n",strerror(errno)); return MSD_ERR; } strncpy(s, pathname, MAXPATHLEN - 1); strxcat(s, ".sem.XXXXXX", MAXPATHLEN); /* 生成唯一的文件,并打开 */ fd = mkstemp(s); if (fd < 0) { return MSD_ERR; } /* 去除引用 */ unlink(s); (*ppl)->fd = fd; //printf("Thread lock init\n"); return fd; }
static void SySetGapRootPath( const Char * string ) { const Char * p; Char * q; Int i; Int n; /* set string to a default value if unset */ if ( string == 0 || *string == 0 ) { string = "./"; } /* ** check if we append, prepend or overwrite. */ if( string[0] == ';' ) { /* Count the number of root directories already present. */ n = 0; while( SyGapRootPaths[n][0] != '\0' ) n++; /* Skip leading semicolon. */ string++; } else if( string[ strlen(string) - 1 ] == ';' ) { /* Count the number of directories in 'string'. */ n = 0; p = string; while( *p ) if( *p++ == ';' ) n++; /* Find last root path. */ for( i = 0; i < MAX_GAP_DIRS; i++ ) if( SyGapRootPaths[i][0] == '\0' ) break; i--; #ifdef HPCGAP n *= 2; // for each root <ROOT> we also add <ROOT/hpcgap> as a root #endif /* Move existing root paths to the back */ if( i + n >= MAX_GAP_DIRS ) return; while( i >= 0 ) { memcpy( SyGapRootPaths[i+n], SyGapRootPaths[i], sizeof(SyGapRootPaths[i+n]) ); i--; } n = 0; } else { /* Make sure to wipe out all possibly existing root paths */ for( i = 0; i < MAX_GAP_DIRS; i++ ) SyGapRootPaths[i][0] = '\0'; n = 0; } /* unpack the argument */ p = string; while ( *p ) { if( n >= MAX_GAP_DIRS ) return; q = SyGapRootPaths[n]; while ( *p && *p != ';' ) { *q = *p++; #ifdef SYS_IS_CYGWIN32 /* fix up for DOS */ if (*q == '\\') *q = '/'; #endif q++; } if ( q == SyGapRootPaths[n] ) { strxcpy( SyGapRootPaths[n], "./", sizeof(SyGapRootPaths[n]) ); } else if ( q[-1] != '/' ) { *q++ = '/'; *q = '\0'; } else { *q = '\0'; } if ( *p ) { p++; } n++; #ifdef HPCGAP // or each root <ROOT> we also add <ROOT/hpcgap> as a root (and first) if( n < MAX_GAP_DIRS ) { strlcpy( SyGapRootPaths[n], SyGapRootPaths[n-1], sizeof(SyGapRootPaths[n]) ); } strxcat( SyGapRootPaths[n-1], "hpcgap/", sizeof(SyGapRootPaths[n-1]) ); n++; #endif } }
void InitSystem ( Int argc, Char * argv [] ) { Char * *ptrlist; UInt i; /* loop variable */ Int res; /* return from option processing function */ /* Initialize global and static variables */ SyCTRD = 1; SyCompilePlease = 0; SyDebugLoading = 0; SyLineEdit = 1; #ifdef HPCGAP SyUseReadline = 0; #else SyUseReadline = 1; #endif SyMsgsFlagBags = 0; SyNrCols = 0; SyNrColsLocked = 0; SyNrRows = 0; SyNrRowsLocked = 0; SyQuiet = 0; SyInitializing = 0; #ifdef SYS_IS_64_BIT SyStorMin = 128 * 1024L; SyStorMax = 2048*1024L; /* This is in kB! */ SyAllocPool = 4096L*1024*1024; /* Note this is in bytes! */ #else SyStorMin = 64 * 1024L; SyStorMax = 1024*1024L; /* This is in kB! */ #ifdef SYS_IS_CYGWIN32 SyAllocPool = 0; /* works better on cygwin */ #else SyAllocPool = 1536L*1024*1024; /* Note this is in bytes! */ #endif #endif SyStorOverrun = 0; SyStorKill = 0; SyUseModule = 1; SyWindow = 0; for (i = 0; i < 2; i++) { UInt j; for (j = 0; j < 7; j++) { SyGasmanNumbers[i][j] = 0; } } preAllocAmount = 4*1024*1024; InitSysFiles(); #ifdef HAVE_LIBREADLINE rl_initialize (); #endif SyInstallAnswerIntr(); #if defined(SYS_DEFAULT_PATHS) SySetGapRootPath( SYS_DEFAULT_PATHS ); #else SySetInitialGapRootPaths(); #endif /* save the original command line for export to GAP */ SyOriginalArgc = argc; SyOriginalArgv = argv; /* scan the command line for options that we have to process in the kernel */ /* we just scan the whole command line looking for the keys for the options we recognise */ /* anything else will presumably be dealt with in the library */ while ( argc > 1 ) { if (argv[1][0] == '-' ) { if ( strlen(argv[1]) != 2 && argv[1][1] != '-') { FPUTS_TO_STDERR("gap: sorry, options must not be grouped '"); FPUTS_TO_STDERR(argv[1]); FPUTS_TO_STDERR("'.\n"); goto usage; } for (i = 0; options[i].shortkey != argv[1][1] && (argv[1][1] != '-' || argv[1][2] == 0 || strcmp(options[i].longkey, argv[1] + 2)) && (options[i].shortkey != 0 || options[i].longkey[0] != 0); i++) ; if (argc < 2 + options[i].minargs) { Char buf[2]; FPUTS_TO_STDERR("gap: option "); FPUTS_TO_STDERR(argv[1]); FPUTS_TO_STDERR(" requires at least "); buf[0] = options[i].minargs + '0'; buf[1] = '\0'; FPUTS_TO_STDERR(buf); FPUTS_TO_STDERR(" arguments\n"); goto usage; } if (options[i].handler) { res = (*options[i].handler)(argv+2, options[i].otherArg); switch (res) { case -1: goto usage; /* case -2: goto fullusage; */ default: ; /* fall through and continue */ } } else res = options[i].minargs; /* recordOption(argv[1][1], res, argv+2); */ argv += 1 + res; argc -= 1 + res; } else { argv++; argc--; } } /* adjust SyUseReadline if no readline support available or for XGAP */ #if !defined(HAVE_LIBREADLINE) SyUseReadline = 0; #endif if (SyWindow) SyUseReadline = 0; /* now that the user has had a chance to give -x and -y, we determine the size of the screen ourselves */ getwindowsize(); /* fix max if it is lower than min */ if ( SyStorMax != 0 && SyStorMax < SyStorMin ) { SyStorMax = SyStorMin; } /* fix pool size if larger than SyStorKill */ if ( SyStorKill != 0 && SyAllocPool != 0 && SyAllocPool > 1024 * SyStorKill ) { SyAllocPool = SyStorKill * 1024; } /* fix pool size if it is given and lower than SyStorMax */ if ( SyAllocPool != 0 && SyAllocPool < SyStorMax * 1024) { SyAllocPool = SyStorMax * 1024; } /* when running in package mode set ctrl-d and line editing */ if ( SyWindow ) { /* SyLineEdit = 1; SyCTRD = 1; */ SyRedirectStderrToStdOut(); syWinPut( 0, "@p", "1." ); } if (SyAllocPool == 0) { /* premalloc stuff */ /* allocate in small chunks, and write something to them * (the GNU clib uses mmap for large chunks and give it back to the * system after free'ing; also it seems that memory is only really * allocated (pagewise) when it is first used) */ ptrlist = (Char **)malloc((1+preAllocAmount/1000)*sizeof(Char*)); for (i = 1; i*1000 < preAllocAmount; i++) { ptrlist[i-1] = (Char *)malloc( 1000 ); if (ptrlist[i-1] != NULL) ptrlist[i-1][900] = 13; } for (i = 1; (i+1)*1000 < preAllocAmount; i++) if (ptrlist[i-1] != NULL) free(ptrlist[i-1]); free(ptrlist); /* ptr = (Char *)malloc( preAllocAmount ); ptr1 = (Char *)malloc(4); if ( ptr != 0 ) free( ptr ); */ } /* should GAP load 'init/lib.g' on initialization */ if ( SyCompilePlease || SyRestoring ) { SyLoadSystemInitFile = 0; } /* the compiler will *not* read in the .gaprc file if ( gaprc && ! ( SyCompilePlease || SyRestoring ) ) { sySetGapRCFile(); } */ #ifdef HAVE_DOTGAPRC /* the users home directory */ if ( getenv("HOME") != 0 ) { strxcpy(DotGapPath, getenv("HOME"), sizeof(DotGapPath)); # if defined(SYS_IS_DARWIN) && SYS_IS_DARWIN /* On Darwin, add .gap to the sys roots, but leave */ /* DotGapPath at $HOME/Library/Preferences/GAP */ strxcat(DotGapPath, "/.gap;", sizeof(DotGapPath)); if (!IgnoreGapRC) { SySetGapRootPath(DotGapPath); } strxcpy(DotGapPath, getenv("HOME"), sizeof(DotGapPath)); strxcat(DotGapPath, "/Library/Preferences/GAP;", sizeof(DotGapPath)); # elif defined(__CYGWIN__) strxcat(DotGapPath, "/_gap;", sizeof(DotGapPath)); # else strxcat(DotGapPath, "/.gap;", sizeof(DotGapPath)); # endif if (!IgnoreGapRC) { SySetGapRootPath(DotGapPath); } DotGapPath[strlen(DotGapPath)-1] = '\0'; /* and in this case we can also expand paths which start with a tilde ~ */ Char userhome[GAP_PATH_MAX]; strxcpy(userhome, getenv("HOME"), sizeof(userhome)); const UInt userhomelen = strlen(userhome); for (i = 0; i < MAX_GAP_DIRS && SyGapRootPaths[i][0]; i++) { const UInt pathlen = strlen(SyGapRootPaths[i]); if (SyGapRootPaths[i][0] == '~' && userhomelen + pathlen < sizeof(SyGapRootPaths[i])) { SyMemmove(SyGapRootPaths[i] + userhomelen, /* don't copy the ~ but the trailing '\0' */ SyGapRootPaths[i] + 1, pathlen); memcpy(SyGapRootPaths[i], userhome, userhomelen); } } } #endif /* now we start */ return; /* print a usage message */ usage: FPUTS_TO_STDERR("usage: gap [OPTIONS] [FILES]\n"); FPUTS_TO_STDERR(" run the Groups, Algorithms and Programming system, Version "); FPUTS_TO_STDERR(SyBuildVersion); FPUTS_TO_STDERR("\n"); FPUTS_TO_STDERR(" use '-h' option to get help.\n"); FPUTS_TO_STDERR("\n"); SyExit( 1 ); }
/** * search_term: Parse CCL search term. * cclp: CCL Parser * qa: Qualifier attributes already applied. * term_list: tokens we accept as terms in context * multi: whether we accept "multiple" tokens * return: pointer to node(s); NULL on error. */ static struct ccl_rpn_node *search_term_x(CCL_parser cclp, ccl_qualifier_t *qa, int *term_list, int multi) { struct ccl_rpn_node *p_top = 0; struct ccl_token *lookahead = cclp->look_token; int and_list = 0; int auto_group = 0; int or_list = 0; char *attset; const char **truncation_aliases; const char *t_default[2]; truncation_aliases = ccl_qual_search_special(cclp->bibset, "truncation"); if (!truncation_aliases) { truncation_aliases = t_default; t_default[0] = "?"; t_default[1] = 0; } if (qual_val_type(qa, CCL_BIB1_STR, CCL_BIB1_STR_AND_LIST, 0)) and_list = 1; if (qual_val_type(qa, CCL_BIB1_STR, CCL_BIB1_STR_AUTO_GROUP, 0)) auto_group = 1; if (qual_val_type(qa, CCL_BIB1_STR, CCL_BIB1_STR_OR_LIST, 0)) or_list = 1; while (1) { struct ccl_rpn_node *p; size_t no, i; int is_phrase = 0; int relation_value = -1; int position_value = -1; int structure_value = -1; int truncation_value = -1; int completeness_value = -1; int len = 0; int left_trunc = 0; int right_trunc = 0; int regex_trunc = 0; int z3958_trunc = 0; size_t max = 200; if (and_list || or_list || !multi) max = 1; /* ignore commas when dealing with and-lists .. */ if (and_list && lookahead && lookahead->kind == CCL_TOK_COMMA) { lookahead = lookahead->next; ADVANCE; continue; } for (no = 0; no < max && is_term_ok(lookahead->kind, term_list); no++) { int this_is_phrase = 0; for (i = 0; i<lookahead->len; i++) if (lookahead->name[i] == ' ') this_is_phrase = 1; if (auto_group) { if (no > 0 && (is_phrase || is_phrase != this_is_phrase)) break; is_phrase = this_is_phrase; } else if (this_is_phrase || no > 0) is_phrase = 1; len += 1+lookahead->len+lookahead->ws_prefix_len; lookahead = lookahead->next; } if (len == 0) break; /* no more terms . stop . */ /* create the term node, but wait a moment before adding the term */ p = ccl_rpn_node_create(CCL_RPN_TERM); p->u.t.attr_list = NULL; p->u.t.term = NULL; if (qa && qa[0]) { const char *n = ccl_qual_get_name(qa[0]); if (n) p->u.t.qual = xstrdup(n); } /* go through all attributes and add them to the attribute list */ for (i=0; qa && qa[i]; i++) { struct ccl_rpn_attr *attr; for (attr = ccl_qual_get_attr(qa[i]); attr; attr = attr->next) switch(attr->kind) { case CCL_RPN_ATTR_STRING: ccl_add_attr_string(p, attr->set, attr->type, attr->value.str); break; case CCL_RPN_ATTR_NUMERIC: if (attr->value.numeric > 0) { /* deal only with REAL attributes (positive) */ switch (attr->type) { case CCL_BIB1_REL: if (relation_value != -1) continue; relation_value = attr->value.numeric; break; case CCL_BIB1_POS: if (position_value != -1) continue; position_value = attr->value.numeric; break; case CCL_BIB1_STR: if (structure_value != -1) continue; structure_value = attr->value.numeric; break; case CCL_BIB1_TRU: if (truncation_value != -1) continue; truncation_value = attr->value.numeric; break; case CCL_BIB1_COM: if (completeness_value != -1) continue; completeness_value = attr->value.numeric; break; } ccl_add_attr_numeric(p, attr->set, attr->type, attr->value.numeric); } } } attset = 0; if (structure_value == -1 && ( auto_group || qual_val_type(qa, CCL_BIB1_STR, CCL_BIB1_STR_WP, &attset)) ) { if (!is_phrase) ccl_add_attr_numeric(p, attset, CCL_BIB1_STR, 2); else ccl_add_attr_numeric(p, attset, CCL_BIB1_STR, 1); } if (qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_REGEX, &attset)) { regex_trunc = 1; /* regex trunc (102) allowed */ } else if (qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_Z3958, &attset)) { z3958_trunc = 1; /* Z39.58 trunc (CCL) trunc allowed */ } /* make the RPN token */ p->u.t.term = (char *)xmalloc(len * 2 + 2); ccl_assert(p->u.t.term); p->u.t.term[0] = '\0'; for (i = 0; i<no; i++) { const char *src_str = cclp->look_token->name; size_t src_len = cclp->look_token->len; if (p->u.t.term[0] && cclp->look_token->ws_prefix_len) { strxcat(p->u.t.term, cclp->look_token->ws_prefix_buf, cclp->look_token->ws_prefix_len); } if (append_term(cclp, src_str, src_len, p->u.t.term, ®ex_trunc, &z3958_trunc, truncation_aliases, i == 0, i == no - 1, &left_trunc, &right_trunc)) { ccl_rpn_delete(p); return NULL; } ADVANCE; } /* make the top node point to us.. */ if (p_top) { struct ccl_rpn_node *tmp; if (or_list) tmp = ccl_rpn_node_create(CCL_RPN_OR); else if (and_list) tmp = ccl_rpn_node_create(CCL_RPN_AND); else tmp = ccl_rpn_node_create(CCL_RPN_AND); tmp->u.p[0] = p_top; tmp->u.p[1] = p; p_top = tmp; } else p_top = p; if (left_trunc && right_trunc) { if (!qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_BOTH, &attset)) { cclp->error_code = CCL_ERR_TRUNC_NOT_BOTH; ccl_rpn_delete(p); return NULL; } ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 3); } else if (right_trunc) { if (!qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_RIGHT, &attset)) { cclp->error_code = CCL_ERR_TRUNC_NOT_RIGHT; ccl_rpn_delete(p); return NULL; } ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 1); } else if (left_trunc) { if (!qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_LEFT, &attset)) { cclp->error_code = CCL_ERR_TRUNC_NOT_LEFT; ccl_rpn_delete(p); return NULL; } ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 2); } else if (regex_trunc == 2) { ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 102); } else if (z3958_trunc == 2) { ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 104); } else { if (qual_val_type(qa, CCL_BIB1_TRU, CCL_BIB1_TRU_CAN_NONE, &attset)) ccl_add_attr_numeric(p, attset, CCL_BIB1_TRU, 100); } if (!multi) break; } if (!p_top) cclp->error_code = CCL_ERR_TERM_EXPECTED; return p_top; }
static int append_term(CCL_parser cclp, const char *src_str, size_t src_len, char *dst_term, int *regex_trunc, int *z3958_trunc, const char **truncation_aliases, int is_first, int is_last, int *left_trunc, int *right_trunc) { size_t j; int quote_mode = 0; for (j = 0; j < src_len; j++) { size_t op_size; if (j > 0 && src_str[j-1] == '\\') { if (*regex_trunc && strchr(REGEX_CHARS "\\", src_str[j])) { *regex_trunc = 2; strcat(dst_term, "\\"); } else if (*z3958_trunc && strchr(CCL_CHARS "\\", src_str[j])) { *z3958_trunc = 2; strcat(dst_term, "\\"); } strxcat(dst_term, src_str + j, 1); } else if (src_str[j] == '"') quote_mode = !quote_mode; else if (!quote_mode && (op_size = cmp_operator(truncation_aliases, src_str + j)) ) { j += (op_size - 1); /* j++ in for loop */ if (*regex_trunc) { strcat(dst_term, ".*"); *regex_trunc = 2; /* regex trunc is really needed */ } else if (*z3958_trunc) { strcat(dst_term, "?"); *z3958_trunc = 2; } else if (is_first && j == 0) *left_trunc = 1; else if (is_last && j == src_len - 1) *right_trunc = 1; else { cclp->error_code = CCL_ERR_TRUNC_NOT_EMBED; return -1; } } else if (!quote_mode && src_str[j] == '#') { if (*regex_trunc) { strcat(dst_term, "."); *regex_trunc = 2; /* regex trunc is really needed */ } else if (*z3958_trunc) { strcat(dst_term, "#"); *z3958_trunc = 2; } else { cclp->error_code = CCL_ERR_TRUNC_NOT_SINGLE; return -1; } } else if (src_str[j] != '\\') { if (*regex_trunc && strchr(REGEX_CHARS, src_str[j])) { *regex_trunc = 2; strcat(dst_term, "\\"); } else if (*z3958_trunc && strchr(CCL_CHARS, src_str[j])) { *z3958_trunc = 2; strcat(dst_term, "\\"); } strxcat(dst_term, src_str + j, 1); } } return 0; }