예제 #1
0
파일: system.c 프로젝트: phs75/gap
/****************************************************************************
**
*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("./");
}
예제 #2
0
파일: system.c 프로젝트: phs75/gap
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;
}
예제 #3
0
파일: msd_lock.c 프로젝트: hq-cml/mossad
/**
 * 功能: 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;
}
예제 #4
0
파일: system.c 프로젝트: phs75/gap
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
    }
}
예제 #5
0
파일: system.c 프로젝트: phs75/gap
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 );
}
예제 #6
0
파일: cclfind.c 프로젝트: nla/yaz
/**
 * 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, &regex_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;
}
예제 #7
0
파일: cclfind.c 프로젝트: nla/yaz
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;
}