Jump to content

Reading a child process's output is impossible without blocking and Windows won't return even after the child ends


Recommended Posts

Hi, I thought I would never post a C/WinAPI related question in this forum ever, but here we are after a few years and me having learnt enough of C to write a basic console program :)

My issue is that I am trying to read my child process's stdout output but ReadFile never returns if the child exits or if it is killed... very strange :unsure:, I have been trying to work my way around this. The options I can think of are:

  1. Create a new thread and check for existance of the process constantly while reading
  2. Somehow make the pipe asynchronous (overlapped) so that I can read it in a non-blocking manner
  3. Fix ReadFile to return when the process ends

Obviously I would prefer No. 3, I just want to make my program work. Here is my code if you guys want to take a look:

// No text highlighting for C/C++ but we have it for C#? Blasphemy!

bool allium_start(struct TorInstance *instance, char *config, allium_pipe *output_pipes) {
    char *cmd;
    
    // Figure out the command string for execution
    if (config) {
        char *parameters = " -f -";
        cmd = malloc(strlen(instance->tor_path) + strlen(parameters) + 1);
        if (!cmd) return false;
        strcpy(cmd, instance->tor_path);
        strcat(cmd, parameters);
    } else cmd = instance->tor_path;
    
    // Prepare startup info with appropriate information
    SecureZeroMemory(&instance->startup_info, sizeof instance->startup_info);
    instance->startup_info.dwFlags = STARTF_USESTDHANDLES;
    
    SECURITY_ATTRIBUTES pipe_secu_attribs = {sizeof(SECURITY_ATTRIBUTES), NULL, true};
    
    HANDLE pipes[2];
    if (output_pipes == NULL) {
        CreatePipe(&pipes[0], &pipes[1], &pipe_secu_attribs, 0);
        output_pipes = pipes;
    }
    instance->startup_info.hStdOutput = output_pipes[1];
    instance->startup_info.hStdError = output_pipes[1];
    instance->stdout_pipe = output_pipes[0]; // Stored for internal reference
    
    if (config) {
        // Reuse the pipes array to store standard input pipes
        CreatePipe(&pipes[0], &pipes[1], &pipe_secu_attribs, 0);
        instance->startup_info.hStdInput = pipes[0];
    }
    
    // Create the process
    bool success = CreateProcessA(
        NULL,
        cmd,
        NULL,
        NULL,
        config ? true : false,
        0,
        NULL,
        NULL,
        &instance->startup_info,
        SecureZeroMemory(&instance->process, sizeof instance->process)
    );
    
    // Free command string if needed
    if (config) free(cmd);
    
    // Write config to Tor's standard input
    unsigned long bytes_written;
    if (success) {
        WriteFile(pipes[1], config, strlen(config), &bytes_written, NULL);
        // Work around for simulating Ctrl + Z which sends the substitution character (ASCII 26),
        // this is needed in order for Tor to detect EOT/EOF while reading the config
        WriteFile(pipes[1], &(char){26}, 1, &bytes_written, NULL);
    }
    CloseHandle(pipes[1]);
    
    // Return on failure
    if (!success) return false;
}

char *allium_read_stdout_line(struct TorInstance *instance) {
    char *buffer = instance->buffer.data;
    
    // Check for valid buffer and allocate if needed
    if (instance->buffer.size == 0 || !buffer) {
        buffer = instance->buffer.data = malloc(instance->buffer.size = 80 + 1);
        if (!buffer) return NULL;
    }
    
    // Process the input
    unsigned int read_len = 0;
    while (true) {
        // Read data
        unsigned long bytes_read;
        if (ReadFile(instance->stdout_pipe, buffer, 1, &bytes_read, NULL) == false || bytes_read == 0) return NULL;
        
        // Check if we have reached end of line
        if (buffer[0] == '\n') break;
        
        // Proceed to the next character
        ++buffer; ++read_len;
        
        // Resize buffer if it is full
        if (read_len == instance->buffer.size) {
            char *new_buffer = malloc(instance->buffer.size += 50);
            if (new_buffer) memcpy(new_buffer, instance->buffer.data, read_len);
            free(instance->buffer.data);
            if (!new_buffer) return NULL;
            instance->buffer.data = new_buffer;
            buffer = instance->buffer.data + read_len;
        }
    }
    
    // Terminate the new line with null character and return
    // Special handling for Windows, terminate at CR if present
    buffer[read_len >= 2 && buffer[-1] == '\r' ? -1 : 0] = '\0';
}

The allium_start function creates the redirection pipes and the child process, the other allium_read_stdout_line function reads from the stdout pipe created by the first function, ReadFile in this function does not return when the child ends or gets killed.

I appriciate the help of the WinAPI gurus here, thanks in advance! :D

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to post
Share on other sites

@Earthshine Yup, was one of the first results that I got a few weeks back when investigating how output redirection works in POSIX.

Sadly it only talks about the POSIX functions to do this, Windows doesn't provide this functionality as far as I am aware. My code for POSIX works like a charm, the issue is only on Windows :(.

The ReadFile documentation mentions:

Quote

When a synchronous read operation reaches the end of a file, ReadFile returns TRUE and sets *lpNumberOfBytesRead to zero.

This does not happen when the process ends... it just never returns!

I wonder how the internal AutoIt functions like Run and StdoutRead work... I am especially keen on how StdoutRead can be non-blocking, does AutoIt use multi-threading to maintain to retrieve the output later? I might use this method, but I would like to avoid it if possible.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to post
Share on other sites

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to post
Share on other sites

It turns out that I lacked basic understanding of how handles work... and that they are duplicated when passed through CreateProcess, so you need to close your own copies of the handles in order for the pipe to properly close when the program exits. I also discovered that inheritence is a bit more complicated, as both handles (each for an end of the pipe) are marked as inheritable by the CreatePipe function during creation... this causes problems yet again by passively duplicating the handles which were not even passed to CreateProcess, you can prevent this by using the SetHandleInformation function. Here is the working code:

bool allium_start(struct TorInstance *instance, char *config, allium_pipe *output_pipes) {
    // Prepare startup info with appropriate information
    SecureZeroMemory(&instance->startup_info, sizeof instance->startup_info);
    instance->startup_info.dwFlags = STARTF_USESTDHANDLES;

    SECURITY_ATTRIBUTES pipe_secu_attribs = {sizeof(SECURITY_ATTRIBUTES), NULL, true};

    HANDLE pipes[2];
    if (output_pipes == NULL) {
        CreatePipe(&pipes[0], &pipes[1], &pipe_secu_attribs, 0);
        output_pipes = pipes;
    }
    SetHandleInformation(output_pipes[0], HANDLE_FLAG_INHERIT, 0);
    instance->startup_info.hStdOutput = output_pipes[1];
    instance->startup_info.hStdError = output_pipes[1];
    instance->stdout_pipe = output_pipes[0]; // Stored for internal reference

    // Create the process
    bool success = CreateProcessA(
        NULL,
        cmd,
        NULL,
        NULL,
        config ? true : false,
        0,
        NULL,
        NULL,
        &instance->startup_info,
        SecureZeroMemory(&instance->process, sizeof instance->process)
    );

    // Close the write end of our stdout handle
    CloseHandle(output_pipes[1]);

    // Return on failure
    if (!success) return false;
}

You can refer to the accepted answer in my StackOverflow question for more details, many thanks to Remy Lebeau and RbMm for answering my questions there.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to post
Share on other sites
  • 2 weeks later...
On 1/29/2019 at 8:50 AM, TheDcoder said:

Just posted this question over at StackOverflow in hopes of getting answers:  -snip- Hope this may help.

Thanks for sharing this link. I have found a couple of answers that are useful and could be implemented in work.

Edited by Jos
spam removed but we still expect that answer whenever you return
Link to post
Share on other sites
  • Moderators

@arnoldfields care to explain why you specifically changed TheDcoder's link in his quote? 

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to post
Share on other sites
  • 2 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By TheDcoder
      Hello, many of you already know I'm working on a new programming language and I need some help to figure out an issue in the parser. I'm posting it here with the hope that someone knowledgeable enough can point out the solution and to also document this issue as I may forget the details if I don't make progress and set it aside.
      Here's the parser:
      /* * This file is part of EasyCodeIt. * * Copyright (C) 2021 TheDcoder <TheDcoder@protonmail.com> * * EasyCodeIt 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 <https://www.gnu.org/licenses/>. */ %define parse.trace %code requires { #define _GNU_SOURCE /* Required to enable (v)asprintf */ #include <stdbool.h> #include "parser/tree.h" #include "parser/parser_internal.h" } %union { double num; struct { char *str; size_t len; } str; bool boolean; struct Expression expr; struct ExpressionList expr_list; } %token UNKNOWN %token WS %token NL '\n' %token COMMENT %token DIRECTIVE %token <num> NUMBER %token <str> STRING %token <boolean> BOOL %token <str> WORD %token <str> MACRO %token <str> VARIABLE %token OPERATOR %token BRACKET %token DOT %token COMMA /* Keywords */ %token K_DIM "Dim" %token K_LOCAL "Local" %token K_GLOBAL "Global" %token K_ENUM "Enum" %token K_CONST "Const" %token K_STATIC "Static" %token K_CONTINUE_CASE "ContinueCase" %token K_CONTINUE_LOOP "ContinueLoop" %token K_DEFAULT "Default" %token K_NULL "Null" %token K_DO "Do" %token K_UNTIL "Until" %token K_WHILE "While" %token K_END_WHILE "WEnd" %token K_FOR "For" %token K_IN "In" %token K_TO "To" %token K_STEP "Step" %token K_NEXT "Next" %token K_EXIT "Exit" %token K_EXITLOOP "ExitLoop" %token K_FUNC "Func" %token K_RETURN "Return" %token K_END_FUNC "EndFunc" %token K_IF "If" %token K_ELSE "Else" %token K_ELSE_IF "ElseIf" %token K_END_IF "EndIf" %token K_REDIM "ReDim" %token K_SELECT "Select" %token K_SWITCH "Switch" %token K_CASE "Case" %token K_END_SELECT "EndSelect" %token K_END_SWITCH "EndSwitch" /* Operators */ %precedence '?' %precedence ':' %left AND "And" OR "Or" %left LT '<' GT '>' LTE "<=" GTE ">=" EQU '=' NEQ "<>" SEQU "==" %left '&' %left '+' '-' %left '*' '/' %left '^' %left NOT "Not" %precedence INVERSION %precedence '.' /* WORKAROUND: Bison can't handle "sandwich" operators which surround the 2nd part of a binary expression */ %precedence '[' %precedence '(' %precedence GROUPING %type <expr> expression %type <expr_list> expression_list %{ int yylex(); void yyerror(const char *s); %} %% top: /* nothing */ | expression_list {print_expr($1.expression);} expression: BOOL {$$ = expr_from_prim(&(struct Primitive){.type = PRI_BOOLEAN, .boolean = $1});} | NUMBER {$$ = expr_from_prim(&(struct Primitive){.type = PRI_NUMBER, .number = $1});} | STRING {$$ = expr_from_str($1.str, $1.len);} | WORD {$$ = expr_from_ident($1.str, $1.len);} | MACRO {$$ = expr_from_ident($1.str, $1.len);} | VARIABLE {$$ = expr_from_ident($1.str, $1.len);} | expression '?' expression ':' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3, &$5}, 3, OP_CON);} | expression "And" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_AND);} | expression "Or" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_OR);} | expression '<' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_LT);} | expression '>' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_GT);} | expression '=' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_EQU);} | expression "<=" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_LTE);} | expression ">=" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_GTE);} | expression "<>" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_NEQ);} | expression "==" expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_SEQU);} | expression '&' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_CAT);} | expression '+' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_ADD);} | expression '-' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_SUB);} | expression '*' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_MUL);} | expression '/' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_DIV);} | expression '^' expression {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_EXP);} | "Not" expression {$$ = expr_from_expr((struct Expression *[]){&$2}, 1, OP_NOT);} | '-' expression %prec INVERSION {$$ = expr_from_expr((struct Expression *[]){&$2}, 1, OP_INV);} /*| expression '.' WORD {$$ = expr_from_expr((struct Expression *[]){&$1, &(struct Expression){expr_from_ident($3.str, $3.len)}}, 2, OP_ACC);}*/ | expression '.' WORD { struct Expression ident_expr = expr_from_ident($3.str, $3.len); $$ = expr_from_expr((struct Expression *[]){&$1, &ident_expr}, 2, OP_ACC); } | expression '[' expression ']' {$$ = expr_from_expr((struct Expression *[]){&$1, &$3}, 2, OP_ACC);} | expression '(' expression_list ')' {$$ = expr_from_call(&$1, &$3);} | expression '(' ')' {$$ = expr_from_call(&$1, NULL);} /* | expression '(' expression_list ')' %prec CALL {$$ = expr_from_call(&$1, &$3);} | expression '(' ')' %prec CALL {$$ = expr_from_call(&$1, NULL);} */ | '(' expression ')' %prec GROUPING {$$ = $2;} expression_list: /* expression {$$ = (struct ExpressionList){.expression = , .list = NULL};} | expression ',' expression_list {$$ = (struct ExpressionList){.expression = &$1, .list = &$3};} */ expression {$$ = exprlist_from_expr(&$1, NULL);} /* | expression ',' expression_list {$$ = exprlist_from_expr(&$1, &$3);} | expression '\n' expression_list {$$ = exprlist_from_expr(&$1, &$3);} */ | expression_list ',' expression {$$ = exprlist_from_expr(&$3, &$1);} | expression_list '\n' expression {$$ = exprlist_from_expr(&$3, &$1);} %% #include "parser/parser.c" And the "parser output" by Bison:
      Terminals unused in grammar UNKNOWN WS NL COMMENT DIRECTIVE OPERATOR BRACKET DOT COMMA "Dim" "Local" "Global" "Enum" "Const" "Static" "ContinueCase" "ContinueLoop" "Default" "Null" "Do" "Until" "While" "WEnd" "For" "In" "To" "Step" "Next" "Exit" "ExitLoop" "Func" "Return" "EndFunc" "If" "Else" "ElseIf" "EndIf" "ReDim" "Select" "Switch" "Case" "EndSelect" "EndSwitch" AND OR LT GT LTE GTE EQU NEQ SEQU NOT Grammar 0 $accept: top $end 1 top: ε 2 | expression_list 3 expression: BOOL 4 | NUMBER 5 | STRING 6 | WORD 7 | MACRO 8 | VARIABLE 9 | expression '?' expression ':' expression 10 | expression "And" expression 11 | expression "Or" expression 12 | expression '<' expression 13 | expression '>' expression 14 | expression '=' expression 15 | expression "<=" expression 16 | expression ">=" expression 17 | expression "<>" expression 18 | expression "==" expression 19 | expression '&' expression 20 | expression '+' expression 21 | expression '-' expression 22 | expression '*' expression 23 | expression '/' expression 24 | expression '^' expression 25 | "Not" expression 26 | '-' expression 27 | expression '.' WORD 28 | expression '[' expression ']' 29 | expression '(' expression_list ')' 30 | expression '(' ')' 31 | '(' expression ')' 32 expression_list: expression 33 | expression_list ',' expression 34 | expression_list '\n' expression Terminals, with rules where they appear $end (0) 0 '\n' (10) 34 '&' (38) 19 '(' (40) 29 30 31 ')' (41) 29 30 31 '*' (42) 22 '+' (43) 20 ',' (44) 33 '-' (45) 21 26 '.' (46) 27 '/' (47) 23 ':' (58) 9 '<' (60) 12 '=' (61) 14 '>' (62) 13 '?' (63) 9 '[' (91) 28 ']' (93) 28 '^' (94) 24 error (256) UNKNOWN (258) WS (259) NL (260) COMMENT (261) DIRECTIVE (262) NUMBER <num> (263) 4 STRING <str> (264) 5 BOOL <boolean> (265) 3 WORD <str> (266) 6 27 MACRO <str> (267) 7 VARIABLE <str> (268) 8 OPERATOR (269) BRACKET (270) DOT (271) COMMA (272) "Dim" (273) "Local" (274) "Global" (275) "Enum" (276) "Const" (277) "Static" (278) "ContinueCase" (279) "ContinueLoop" (280) "Default" (281) "Null" (282) "Do" (283) "Until" (284) "While" (285) "WEnd" (286) "For" (287) "In" (288) "To" (289) "Step" (290) "Next" (291) "Exit" (292) "ExitLoop" (293) "Func" (294) "Return" (295) "EndFunc" (296) "If" (297) "Else" (298) "ElseIf" (299) "EndIf" (300) "ReDim" (301) "Select" (302) "Switch" (303) "Case" (304) "EndSelect" (305) "EndSwitch" (306) AND (307) "And" (308) 10 OR (309) "Or" (310) 11 LT (311) GT (312) LTE (313) "<=" (314) 15 GTE (315) ">=" (316) 16 EQU (317) NEQ (318) "<>" (319) 17 SEQU (320) "==" (321) 18 NOT (322) "Not" (323) 25 INVERSION (324) GROUPING (325) Nonterminals, with rules where they appear $accept (89) on left: 0 top (90) on left: 1 2 on right: 0 expression <expr> (91) on left: 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 on right: 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 expression_list <expr_list> (92) on left: 32 33 34 on right: 2 29 33 34 State 0 0 $accept: • top $end NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 $default reduce using rule 1 (top) top go to state 10 expression go to state 11 expression_list go to state 12 State 1 4 expression: NUMBER • $default reduce using rule 4 (expression) State 2 5 expression: STRING • $default reduce using rule 5 (expression) State 3 3 expression: BOOL • $default reduce using rule 3 (expression) State 4 6 expression: WORD • $default reduce using rule 6 (expression) State 5 7 expression: MACRO • $default reduce using rule 7 (expression) State 6 8 expression: VARIABLE • $default reduce using rule 8 (expression) State 7 26 expression: '-' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 13 State 8 25 expression: "Not" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 14 State 9 31 expression: '(' • expression ')' NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 15 State 10 0 $accept: top • $end $end shift, and go to state 16 State 11 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' 32 expression_list: expression • '?' shift, and go to state 17 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 32 (expression_list) State 12 2 top: expression_list • 33 expression_list: expression_list • ',' expression 34 | expression_list • '\n' expression '\n' shift, and go to state 36 ',' shift, and go to state 37 $default reduce using rule 2 (top) State 13 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 26 | '-' expression • 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 26 (expression) State 14 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 25 | "Not" expression • 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 25 (expression) State 15 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' 31 | '(' expression • ')' '?' shift, and go to state 17 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 ')' shift, and go to state 38 State 16 0 $accept: top $end • $default accept State 17 9 expression: expression '?' • expression ':' expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 39 State 18 10 expression: expression "And" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 40 State 19 11 expression: expression "Or" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 41 State 20 12 expression: expression '<' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 42 State 21 13 expression: expression '>' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 43 State 22 15 expression: expression "<=" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 44 State 23 16 expression: expression ">=" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 45 State 24 14 expression: expression '=' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 46 State 25 17 expression: expression "<>" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 47 State 26 18 expression: expression "==" • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 48 State 27 19 expression: expression '&' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 49 State 28 20 expression: expression '+' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 50 State 29 21 expression: expression '-' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 51 State 30 22 expression: expression '*' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 52 State 31 23 expression: expression '/' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 53 State 32 24 expression: expression '^' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 54 State 33 27 expression: expression '.' • WORD WORD shift, and go to state 55 State 34 28 expression: expression '[' • expression ']' NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 56 State 35 29 expression: expression '(' • expression_list ')' 30 | expression '(' • ')' NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 ')' shift, and go to state 57 expression go to state 11 expression_list go to state 58 State 36 34 expression_list: expression_list '\n' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 59 State 37 33 expression_list: expression_list ',' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 60 State 38 31 expression: '(' expression ')' • $default reduce using rule 31 (expression) State 39 9 expression: expression • '?' expression ':' expression 9 | expression '?' expression • ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '?' shift, and go to state 17 ':' shift, and go to state 61 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 State 40 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 10 | expression "And" expression • 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 10 (expression) State 41 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 11 | expression "Or" expression • 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 11 (expression) State 42 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 12 | expression '<' expression • 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 12 (expression) State 43 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 13 | expression '>' expression • 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 13 (expression) State 44 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 15 | expression "<=" expression • 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 15 (expression) State 45 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 16 | expression ">=" expression • 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 16 (expression) State 46 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 14 | expression '=' expression • 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 14 (expression) State 47 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 17 | expression "<>" expression • 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 17 (expression) State 48 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 18 | expression "==" expression • 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 18 (expression) State 49 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 19 | expression '&' expression • 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 19 (expression) State 50 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 20 | expression '+' expression • 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 20 (expression) State 51 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 21 | expression '-' expression • 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 21 (expression) State 52 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 22 | expression '*' expression • 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 22 (expression) State 53 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 23 | expression '/' expression • 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 23 (expression) State 54 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 24 | expression '^' expression • 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 24 (expression) State 55 27 expression: expression '.' WORD • $default reduce using rule 27 (expression) State 56 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 28 | expression '[' expression • ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' '?' shift, and go to state 17 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 ']' shift, and go to state 62 State 57 30 expression: expression '(' ')' • $default reduce using rule 30 (expression) State 58 29 expression: expression '(' expression_list • ')' 33 expression_list: expression_list • ',' expression 34 | expression_list • '\n' expression '\n' shift, and go to state 36 ')' shift, and go to state 63 ',' shift, and go to state 37 State 59 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' 34 expression_list: expression_list '\n' expression • '?' shift, and go to state 17 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 34 (expression_list) State 60 9 expression: expression • '?' expression ':' expression 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' 33 expression_list: expression_list ',' expression • '?' shift, and go to state 17 "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 33 (expression_list) State 61 9 expression: expression '?' expression ':' • expression NUMBER shift, and go to state 1 STRING shift, and go to state 2 BOOL shift, and go to state 3 WORD shift, and go to state 4 MACRO shift, and go to state 5 VARIABLE shift, and go to state 6 '-' shift, and go to state 7 "Not" shift, and go to state 8 '(' shift, and go to state 9 expression go to state 64 State 62 28 expression: expression '[' expression ']' • $default reduce using rule 28 (expression) State 63 29 expression: expression '(' expression_list ')' • $default reduce using rule 29 (expression) State 64 9 expression: expression • '?' expression ':' expression 9 | expression '?' expression ':' expression • 10 | expression • "And" expression 11 | expression • "Or" expression 12 | expression • '<' expression 13 | expression • '>' expression 14 | expression • '=' expression 15 | expression • "<=" expression 16 | expression • ">=" expression 17 | expression • "<>" expression 18 | expression • "==" expression 19 | expression • '&' expression 20 | expression • '+' expression 21 | expression • '-' expression 22 | expression • '*' expression 23 | expression • '/' expression 24 | expression • '^' expression 27 | expression • '.' WORD 28 | expression • '[' expression ']' 29 | expression • '(' expression_list ')' 30 | expression • '(' ')' "And" shift, and go to state 18 "Or" shift, and go to state 19 '<' shift, and go to state 20 '>' shift, and go to state 21 "<=" shift, and go to state 22 ">=" shift, and go to state 23 '=' shift, and go to state 24 "<>" shift, and go to state 25 "==" shift, and go to state 26 '&' shift, and go to state 27 '+' shift, and go to state 28 '-' shift, and go to state 29 '*' shift, and go to state 30 '/' shift, and go to state 31 '^' shift, and go to state 32 '.' shift, and go to state 33 '[' shift, and go to state 34 '(' shift, and go to state 35 $default reduce using rule 9 (expression) And finally a minimal reproduction of the issue I'm facing:
      TheDcoder@arch /m/d/P/C/E/build (master)> eci 1\n2 Starting parse Entering state 0 Stack now 0 Reading a token Next token is token NUMBER () Shifting token NUMBER () Entering state 1 Stack now 0 1 Reducing stack by rule 4 (line 130): $1 = token NUMBER () -> $$ = nterm expression () Entering state 11 Stack now 0 11 Reading a token Next token is token NL () Reducing stack by rule 32 (line 168): $1 = nterm expression () -> $$ = nterm expression_list () Entering state 12 Stack now 0 12 Next token is token NL () Reducing stack by rule 2 (line 126): $1 = nterm expression_list () { "op": "No Operation", "args": [ 1.0 ] } -> $$ = nterm top () Entering state 10 Stack now 0 10 Next token is token NL () 2: syntax error at Error: popping nterm top () Stack now 0 Cleanup: discarding lookahead token NL () Stack now 0 Now I will explain the issue:
      I am trying to parse several different expressions and construct an "expression list" from them, however my parser immediately reduces the first expression to the "top" rule, but what I want is for it to make an "expression_list" which combines the following expression which is separated by a NL.
      This fact can be observed in the debug output from the reproduction script parse attempt, after the parser enters state 12 it immediately uses rule 2 to reduce to "top", but what we want is for it to use rule 34 and reduce to another "expression_list".
      The reason why I think this happens is because the reduction to top simply consumes less tokens and satisfies the parser, and as far as I can tell there is no way to force Bison to be "greedy" when reducing an "expression_list".
      So I'm unsure how to proceed further, I think we have to change the parser but I do not know how. I tried some silly things (like making another "super_top" non-terminal etc.) but those don't compile and produce a ton of conflicts 😕
    • By UEZ
      I'm searching for a way to set an icon for a system menu entry in the console window. I can add / remove entries but I didn't find a way to set an icon for the entry I made.
      Example:
      #AutoIt3Wrapper_Change2CUI=y #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiMenu.au3> #include <WindowsConstants.au3> Global $id_Test = 5000 Global $hConsole = HWnd(DllCall("kernel32.dll", "hwnd", "GetConsoleWindow")[0]) If Not $hConsole Then Exit HotKeySet("{ESC}", "_Exit") Global $hSysmenu = _GUICtrlMenu_GetSystemMenu($hConsole) Global $iCount = _GUICtrlMenu_GetItemCount ($hSysmenu) _GUICtrlMenu_InsertMenuItem($hSysmenu, $iCount, "Test", $id_Test) _GDIPlus_Startup() $hBitmap_GDI = _GDIPlus_BitmapCreateFromMemory(_Test(), True) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBitmap_GDI = ' & $hBitmap_GDI & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $hBmp1 = _WinAPI_CreateSolidBitmap($hConsole, 0xFF0000, 16, 16) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBmp1 = ' & $hBmp1 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $hBmp2 = _WinAPI_CreateSolidBitmap($hConsole, 0x00FF00, 16, 16) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hBmp2 = ' & $hBmp2 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;ConsoleWrite(_GUICtrlMenu_SetItemBmp($hSysmenu, $id_Test, $hBitmap_GDI, False) & @CRLF) ConsoleWrite(_GUICtrlMenu_SetItemBitmaps($hSysmenu, $id_Test, $hBmp1, $hBmp2, False) & ", " & @error & @CRLF) ;_GUICtrlMenu_SetItemBmp($hSysmenu, $id_Test, 8, False) ;set the default close icon _GDIPlus_Shutdown() Do Sleep(1000) Until False Func _Exit() ConsoleWrite("Bye..." & @CRLF) _GUICtrlMenu_DeleteMenu ($hSysmenu, $id_Test, False) _WinAPI_DeleteObject($hBitmap_GDI) _WinAPI_DeleteObject($hBmp1) _WinAPI_DeleteObject($hBmp2) Exit EndFunc ;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2020-06-05 Func _Test($bSaveBinary = False, $sSavePath = @ScriptDir) Local $Test $Test &= 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAADKElEQVQ4yz2RT2gcdRTHP7+Z36y7yzZZdvJv22i0rBpiAwnWCMZrUCGIBxEvpQSEHAQhePLkyUKg6Em9iZCcahH0pFYxkIqiIdHKYmPUUHcDmU2TuJnZzc7s/H7PQ5M8ePAu7/M+X56y1hKGYY+IOEDqOI6TzWY1gFIKEcF1XRzHUWmaJnF8bHBy5pfbnz9fb0hBh2F4bm5ubjWKogudTqdVqVT0/Py853kehUKBQqHA2tqaVKtVfenS2P6HH396PDri9D9+cdC/8dkXNW2t9fb29spRFPmtVqtULBaVMYZ8Pk82m8X3farVKjdv3qCn+FbpnFuXfNpQkkwlX33z3RtaKYXW2mqtcV1XtNZks9kzQCaTIeNp4sSh8rAnzSe0HO5bt1arHR51y79pEcEYo05Aylp7OqOUIk0TRp+aYO5Ki3B3VR3s70pictzZGlC5jHW0UgprLVEU4Xke29vbLCwsoLXGcRRxYjk/2MtLz2X4/tvbaO3y9XoPlUe7CI7VAMYYPM+jXC5jrcUYAwipUeSzHhV/k59+bFK5OMytOxco9ezQTQ2A4ujoqDQ+Ph4sLS2JiNiDgwM5PDyQ3SCQ/5ptubv6rsy9XJIfvnxbNv/8W+7d+9deu/aeTE9PB2EYljSAiKje3l7SNCUIAkDQXp77f3zE4uJ1Xnv9KoWRK+zs1DlfHiCXy2OtBcA5AdDpdHBdl4F+n77BEdz2z3zw/iKvvHqVZ194h0wmz0B/Ca094jjmtE4NEBFarRa7jfvkHgqp/rrKxOQzjF6+wtY/u4g9Jo5TfL+EiGCtxVqLFhGUUhhjsNZgrcvqrU948rFhKlNvEkUdtNvBoFEqPVtUSqGUQiulaDabtNttPC/D5t3fqTU0Y5dfpNFogFhEOLsaxzHtdpsgCNT6+rrSSZIwOztrhoeH' $Test &= 'qdfrRmutJp6e4q+tKsbYs3in7+7r65OhoSE9MzNjkiRBt9ttkiRxjTHkcjl3bGxMPYhjSdP0rLvdLt1uF9d1BcDzPHdyclL0yspKuLGxcT0IgkeKxaINgsADXBFxAefEQB4ImNT3/W4Yhk6z2awtLy9H/wPnrsNEnFPl4QAAAABJRU5ErkJggg==' Local $bString = _WinAPI_Base64Decode($Test) If @error Then Return SetError(1, 0, 0) $bString = Binary($bString) If $bSaveBinary Then Local Const $hFile = FileOpen($sSavePath & "\AutoSave_16x16_04.png", 18) If @error Then Return SetError(2, 0, $bString) FileWrite($hFile, $bString) FileClose($hFile) EndIf Return $bString EndFunc ;==>_Test Func _WinAPI_Base64Decode($sB64String) Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "") Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]") $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "") Return DllStructGetData($bBuffer, 1) EndFunc ;==>_WinAPI_Base64Decode  
      You must compile and run it to see the menu entry in the console window.

       
      Any idea?
    • By UEZ
      Here another approach to check if a script was already started using atoms and semaphores.
       
      Atom:
      #include <MsgBoxConstants.au3> Global $iSingleton = Singleton() If Not $iSingleton Then Exit MsgBox($MB_TOPMOST, "Singleton Test", "Process is already running!") EndIf MsgBox($MB_TOPMOST, "Singleton Test", "Singleton atom initialized: " & $iSingleton) Singleton_Delete($iSingleton) ; #FUNCTION# ==================================================================================================================== ; Name ..........: Singleton ; Description ...: Checks if the script has been started already. ; Syntax ........: Singleton([$sOccurrenceName = @ScriptFullPath]) ; Parameters ....: $sOccurrenceName - [optional] a string value. Default is @ScriptFullPath. ; Return values .: If the function succeeds, the return value is the newly created atom or 0 else error is set and false is returned. ; Author ........: UEZ ; Modified ......: ; Remarks .......: If Singleton finds the atom it will return 0 and the atom token will be set to extended macro. It can be used to get the atom string using _WinAPI_AtomGlobalGetName. ; Related .......: ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalfindatomw ; https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globaladdatomw ; Example .......: No ; =============================================================================================================================== Func Singleton($sOccurrenceName = @ScriptFullPath) Local $iFind = _WinAPI_AtomGlobalFind($sOccurrenceName) If @error Then Return SetError(1, 0, False) If $iFind Then Return SetExtended($iFind, 0) Local $iAtom = _WinAPI_AtomGlobalAdd($sOccurrenceName) If @error Then Return SetError(2, 0, False) Return $iAtom EndFunc ;==>Singleton ; #FUNCTION# ==================================================================================================================== ; Name ..........: Singleton_Delete ; Description ...: Deletes the atom generated by the first started script. ; Syntax ........: Singleton_Delete($iAtom) ; Parameters ....: $iAtom - an integer value which was generated by Singleton ; Return values .: True if successful else false. ; Author ........: UEZ ; Modified ......: ; Remarks .......: Don't forget to call Singleton_Delete before first started script ends. ; Related .......: ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globaldeleteatom ; Example .......: No ; =============================================================================================================================== Func Singleton_Delete($iAtom) _WinAPI_AtomGlobalDelete($iAtom) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>Singleton_Delete ;internal functions Func _WinAPI_AtomGlobalFind($sAtomString) Local $aReturn = DllCall("kernel32.dll", "short", "GlobalFindAtomW", "wstr", $sAtomString) If @error Then Return SetError(1, 0, -1) Return $aReturn[0] EndFunc ;==>_WinAPI_AtomGlobalFind Func _WinAPI_AtomGlobalAdd($sAtomString) Local $aReturn = DllCall("kernel32.dll", "short", "GlobalAddAtomW", "wstr", $sAtomString) If @error Then Return SetError(1, 0, -1) Return $aReturn[0] EndFunc ;==>_WinAPI_AtomGlobalAdd Func _WinAPI_AtomGlobalDelete($nAtom) Local $aReturn = DllCall("kernel32.dll", "short", "GlobalDeleteAtom", "short", $nAtom) If @error Then Return SetError(1, 0, -1) Return $aReturn[0] = 0 EndFunc ;==>_WinAPI_AtomGlobalDelete Func _WinAPI_AtomGlobalGetName($nAtom, $iBufferSize = 512) Local $tBufferAtom = DllStructCreate("wchar name[" & $iBufferSize & "]") Local $aReturn = DllCall("kernel32.dll", "uint", "GlobalGetAtomNameW", "short", $nAtom, "struct*", $tBufferAtom, "int", $iBufferSize) If @error Or Not $aReturn[0] Then Return SetError(1, 0, -1) Return $tBufferAtom.name EndFunc ;==>_WinAPI_AtomGlobalGetName  
      Semaphore:
      #include <MsgBoxConstants.au3> #include <WinAPIError.au3> Global $iSingleton = Singleton("&]8h/x87</htFV4-K*&.b.w~") If Not $iSingleton Then Exit MsgBox($MB_TOPMOST, "Singleton Test", "Process is already running!") EndIf MsgBox($MB_TOPMOST, "Singleton Test", "Singleton Semaphore initialized: " & $iSingleton) ; #FUNCTION# ==================================================================================================================== ; Name ..........: Singleton ; Description ...: Checks if the script has been started already. ; Syntax ........: Singleton($sOccurrenceName) ; Parameters ....: $sOccurrenceName - a string value which will be used to create the semaphore handle. ; Return values .: True if Singleton started the first time. False if script was already started ; Author ........: UEZ ; Modified ......: ; Remarks .......: The system closes the handle automatically when the process terminates. The semaphore object is destroyed when its last handle has been closed. ; Related .......: ; Link ..........: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsemaphorea ; Example .......: No ; =============================================================================================================================== Func Singleton($sOccurrenceName) If StringLen($sOccurrenceName) > 260 Then $sOccurrenceName = StringLeft($sOccurrenceName, 260) Local $aReturn = DllCall("kernel32.dll", "handle", "CreateSemaphoreA", "ptr", Null, "long", 0, "long", 1, "str", $sOccurrenceName) If @error Or Not $aReturn[0] Then Return SetError(1, 0, -1) Return SetExtended($aReturn[0], $aReturn[0] And _WinAPI_GetLastErrorMessage() = "The operation completed successfully.") EndFunc ;==>Singleton  
      Just start the script twice to see if it works.
      The disadvantage of using atoms is that atoms have a memory that means when your app is crashing or you forgot to delete the atom then the atom does still have the $sOccurrenceName saved and thus Singleton will not work if you use the same same value for $sOccurrenceName.
      With semaphore you don't have this issue.
       
      Thanks to jj2007 and SARG.
    • By BlueSkyMemory
      Hello guys! I'm a rookie in AutoIt lol.
      I've tried to looking up in MSDN and the UDFs, but it can only get the GUID of a usual partition and with the GUID to control it. Now I have no ways😥.
      Thanks a lot for your help!
    • By emendelson
      Using some very ingenious scripts that I found on this forum, I've put together a special-purpose folder watcher that watches a specified folder for printer output files and then either send them to a printer or converts them to a PDF and prints or opens the PDF. The page about this utility is here:
      http://www.columbia.edu/~em36/printfileprinter.html
      The one serious problem that it has is that it seems not to detect a new file if there are more than two or three files already in the watched folder. I can't figure out what I'm doing wrong, and will be grateful for any help. Here is the relevant part of the script. I've left out the functions that test whether the file is in use or not, and that send the raw data to the printer or create a PDF, etc. I hope there's enough code here to make sense of it, and will be very grateful for any help. Again, the problem is that the script doesn't detect newly-created files in watched folders with more than a very few files already in it.
      My totally ignorant guess is that the problem is in the line $iID = _WinAPI_WaitForMultipleObjects(2, $paObj, 0, 0) - but I don't know how to change it and of course I'm only guessing whether it's relevant or not. Many thanks
       
      Global $g_ahObj[2] $g_ahObj[0] = _WinAPI_FindFirstChangeNotification($watchPath, $FILE_NOTIFY_CHANGE_FILE_NAME) $g_ahObj[1] = _WinAPI_FindFirstChangeNotification($watchPath, $FILE_NOTIFY_CHANGE_DIR_NAME) If (Not $g_ahObj[0]) Or (Not $g_ahObj[1]) Then MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), 'Error', 'Unable to create change notification.') Exit EndIf Local $tObjs = DllStructCreate('ptr;ptr') Local $paObj = DllStructGetPtr($tObjs) For $i = 0 To 1 DllStructSetData($tObjs, $i + 1, $g_ahObj[$i]) Next Local $iID While 1 Sleep(100) $select = 0 $print = 0 $format = "" Local $tempPDF $tempPDF = 0 $iID = _WinAPI_WaitForMultipleObjects(2, $paObj, 0, 0) Switch $iID Case 0 ; WAIT_OBJECT_0 ; ConsoleWrite('A file was created, renamed, or deleted in the directory.' & @CRLF) Local $hSearch = FileFindFirstFile($watchPath & "\*") Local $sFileName = "", $iResult = 0 Local $sFilePath = "" While 1 $sFileName = FileFindNextFile($hSearch) ; If there is no more file matching the search. If @error Then ExitLoop $sFilePath = $watchPath & "\" & $sFileName Local $fileUsed $fileUsed = 0 $fileUsed = _FileIsUsed($sFilePath) If $fileUsed = 1 Then While 1 Sleep(100) $fileUsed = _FileIsUsed($sFilePath) If $fileUsed = 0 Then ExitLoop WEnd EndIf If StringInStr($sFileName, "raw") Then If StringInStr($sFileName, "select") Then $select = 1 PrintRawFile($sFilePath, $select) Else If StringInStr($sFileName, "lg.") Then $pageSize = "legal" ElseIf StringInStr($sFileName, "a4.") Then $pageSize = "a4" ElseIf StringInStr($sFileName, "us.") Then $pageSize = "letter" EndIf $pdfTemp = 0 If StringLower(StringLeft($sFileName, 7) = "pdftemp") Then $pdfTemp = 1 If StringInStr($sFileName, ".pcl") Then $format = "pcl" $print = 1 If StringLeft($sFileName, 6) = "select" Then $select = 1 $print = 1 ElseIf StringLeft($sFileName, 3) = "pdf" Then $select = 0 $print = 0 EndIf MakePDF($sFilePath, $format, $print, $select, $pageSize, $pdfTemp) ElseIf StringInStr($sFileName, ".ps") Then $format = "ps" $print = 1 If StringLeft($sFileName, 6) = "select" Then $select = 1 $print = 1 ElseIf StringLeft($sFileName, 3) = "pdf" Then $select = 0 $print = 0 EndIf MakePDF($sFilePath, $format, $print, $select, $pageSize, $pdfTemp) ElseIf StringInStr($sFileName, ".esc") Then Sleep(200) $format = "epson" $print = 1 If StringLeft($sFileName, 6) = "select" Then $select = 1 $print = 1 ElseIf StringLeft($sFileName, 3) = "pdf" Then $select = 0 $print = 0 EndIf MakePDF($sFilePath, $format, $print, $select, $pageSize, $pdfTemp) ElseIf StringInStr($sFileName, ".prn") Then $format = GetFileFormat($sFilePath) $print = 1 If StringLeft($sFileName, 6) = "select" Then $select = 1 $print = 1 ElseIf StringLeft($sFileName, 3) = "pdf" Then $select = 0 $print = 0 EndIf ConsoleWrite("PRN test format: " & $format & @CRLF) MakePDF($sFilePath, $format, $print, $select, $pageSize, $pdfTemp) EndIf EndIf ; Display the file name. ; $iResult = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_OKCANCEL), "", $watchPath & "\" & $sFileName) ;~ RunWait(@ComSpec & " /c notepad.exe " & $watchPath & "\" & $sFileName) ;~ FileDelete($watchPath & "\" & $sFileName) If $iResult <> $IDOK Then ExitLoop ; If the user clicks on the cancel/close button. WEnd ; Close the search handle. FileClose($hSearch) Case 1 ; WAIT_OBJECT_0 + 1 ; ConsoleWrite('A directory was created, renamed, or deleted.' & @CRLF) Case Else ContinueLoop EndSwitch If Not _WinAPI_FindNextChangeNotification($g_ahObj[$iID]) Then MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), 'Error', 'Unexpected error.') Exit EndIf WEnd  
×
×
  • Create New...