tcl_language_support #19
+1
-1
@@ -123,4 +123,4 @@
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,6 +514,31 @@
|
||||
"set syslog [MOM_ask_syslog_name]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "MOM_ask_ude_info",
|
||||
"kind": "function",
|
||||
"description": "This command is used to retrieve the information about a user-defined event (UDE) of a specified object.",
|
||||
"format": "MOM_ask_ude_info object_name object_type <Start/End/\"\">",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Object_name",
|
||||
"desc": "The name of the object to which the UDE is attached. It can be a group, an operation, a tool, a geometry, or a method."
|
||||
},
|
||||
{
|
||||
"name": "object_type",
|
||||
"desc": "The type of the object to which the UDE is attached. The following types are available.(group || operation/oper || tool || geometry/geom || method/meth)"
|
||||
},
|
||||
{
|
||||
"name": "Start/End/\"\"",
|
||||
"desc": "This parameter is optional. Indicates whether you want to retrieve the UDE attached to the start event, end event, or both. If it is empty, returns the UDEs attached to the specified operation."
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
"0 - The UDE information retrieval failed.",
|
||||
"1 - The UDE information successfully retrieved."
|
||||
],
|
||||
"example": []
|
||||
},
|
||||
{
|
||||
"label": "MOM_cancel_suppress_force_once_per_event",
|
||||
"kind": "function",
|
||||
|
||||
@@ -54,7 +54,7 @@ from tclint.violations import Violation
|
||||
from plugins.poco_plugin import commands
|
||||
from tools import checks, parser
|
||||
from tools.semantic_tokens import _Highlighter, TOKEN_TYPES, TokenModifier
|
||||
from tools.completion_items import _Completion
|
||||
from tools.completion_items import completion
|
||||
|
||||
DIAGNOSTIC_SOURCE = "nx-post-support"
|
||||
|
||||
@@ -62,7 +62,7 @@ DIAGNOSTIC_SOURCE = "nx-post-support"
|
||||
class TclLanguageServer(server.LanguageServer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.parser = parser.CustomParser() # Parser()
|
||||
self.parser = Parser()
|
||||
for command in commands:
|
||||
self.parser._commands.update(command)
|
||||
self.diagnostics = {}
|
||||
@@ -215,10 +215,10 @@ def did_change(params: lsp.DidChangeTextDocumentParams) -> None:
|
||||
"""LSP handler for textDocument/didChange request"""
|
||||
document = LSP_SERVER.workspace.get_text_document(params.text_document.uri)
|
||||
LSP_SERVER.compute_diagnostics(document)
|
||||
ci = _Completion()
|
||||
completion.reset()
|
||||
tree = LSP_SERVER.parser.parse(document.source)
|
||||
tree.accept(ci, recurse=True)
|
||||
LSP_SERVER._custom_functions = ci.custom_functions
|
||||
tree.accept(completion, recurse=True)
|
||||
log_to_output(tree.pretty(2))
|
||||
|
||||
|
||||
@LSP_SERVER.feature(
|
||||
@@ -254,7 +254,7 @@ def on_completion(params: lsp.CompletionParams) -> list[lsp.CompletionItem]:
|
||||
standard_items.tcl_keyword_list
|
||||
+ standard_items.nx_procs
|
||||
+ standard_items.nx_variables
|
||||
+ LSP_SERVER._custom_functions
|
||||
+ completion.custom_functions
|
||||
)
|
||||
return lsp.CompletionList(is_incomplete=False, items=items)
|
||||
|
||||
|
||||
@@ -1,4 +1,57 @@
|
||||
from enum import Enum
|
||||
from tclint.syntax_tree import Visitor, BareWord, Command
|
||||
from tclint.violations import Violation, Rule
|
||||
|
||||
|
||||
class Rules(Enum):
|
||||
VALIDATION = "validation"
|
||||
OPTIONAL_ARG_POSITION = "optinal_args"
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class CommandArgsCheck(Visitor):
|
||||
def __init__(self):
|
||||
self._violations = []
|
||||
|
||||
def check(self, _, tree):
|
||||
self._violations.clear()
|
||||
tree.accept(self, recurse=True)
|
||||
return self._violations
|
||||
|
||||
def visit_command(self, command: Command):
|
||||
if (
|
||||
not hasattr(command.routine, "contents")
|
||||
or command.routine.contents != "proc"
|
||||
):
|
||||
return
|
||||
if len(command.args) < 2:
|
||||
return
|
||||
|
||||
args_node = command.args[1]
|
||||
if not hasattr(args_node, "children"):
|
||||
return
|
||||
|
||||
found_optional = False
|
||||
for arg in args_node.children:
|
||||
# Required argument
|
||||
if isinstance(arg, BareWord):
|
||||
if found_optional:
|
||||
self._violations.append(
|
||||
Violation(
|
||||
Rules.OPTIONAL_ARG_POSITION,
|
||||
"Required argument follows optional one",
|
||||
arg.pos,
|
||||
arg.end_pos,
|
||||
)
|
||||
)
|
||||
# Optional argument
|
||||
elif hasattr(arg, "children") and len(arg.children) >= 2:
|
||||
found_optional = True
|
||||
|
||||
|
||||
def get_checkers():
|
||||
checkers = ()
|
||||
checkers = (CommandArgsCheck(),)
|
||||
|
||||
return checkers
|
||||
|
||||
@@ -24,6 +24,9 @@ class _Completion(Visitor):
|
||||
def custom_functions(self) -> list[lsp.CompletionItem]:
|
||||
return self._custom_functions
|
||||
|
||||
def reset(self):
|
||||
self._custom_functions = []
|
||||
|
||||
def visit_command(self, command):
|
||||
routine = command.routine
|
||||
|
||||
@@ -37,3 +40,6 @@ class _Completion(Visitor):
|
||||
label=first_arg.value, kind=lsp.CompletionItemKind.Function
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
completion = _Completion()
|
||||
|
||||
+62
-153
@@ -1,12 +1,4 @@
|
||||
from tclint.parser import (
|
||||
Parser,
|
||||
_is_bool_literal,
|
||||
_is_float_literal,
|
||||
_is_float_prefix,
|
||||
_is_function,
|
||||
_is_int_literal,
|
||||
_is_int_prefix,
|
||||
)
|
||||
from tclint.parser import Parser, _strip_ws
|
||||
from tclint.lexer import (
|
||||
STATE_BRACEDWORD,
|
||||
TOK_BACKSLASH_NEWLINE,
|
||||
@@ -35,29 +27,21 @@ from tclint.syntax_tree import (
|
||||
|
||||
|
||||
class CustomParser(Parser):
|
||||
def _strip_ws(parse_func):
|
||||
"""Decorator used by expression parser for stripping whitespace around a node."""
|
||||
|
||||
def func(parser, ts):
|
||||
while ts.type() in {TOK_WS, TOK_BACKSLASH_NEWLINE, TOK_NEWLINE}:
|
||||
ts.next()
|
||||
|
||||
node = parse_func(parser, ts)
|
||||
|
||||
while ts.type() in {TOK_WS, TOK_BACKSLASH_NEWLINE, TOK_NEWLINE}:
|
||||
ts.next()
|
||||
|
||||
return node
|
||||
|
||||
return func
|
||||
|
||||
@_strip_ws
|
||||
def _parse_expression(self, ts):
|
||||
op1 = self._parse_operand(ts)
|
||||
expr = op1
|
||||
|
||||
# Add TOK_BACKSLASH_NEWLINE to the tokens we need to skip
|
||||
while ts.type() == TOK_BACKSLASH_NEWLINE:
|
||||
ts.next()
|
||||
|
||||
# last condition is hack to break out of expression in case we're in ternary op
|
||||
if ts.type() not in {TOK_EOF, TOK_RPAREN} and ts.value() not in {":", ","}:
|
||||
if ts.type() not in {
|
||||
TOK_EOF,
|
||||
TOK_RPAREN,
|
||||
TOK_BACKSLASH_NEWLINE,
|
||||
} and ts.value() not in {":", ","}:
|
||||
if ts.value() == "?":
|
||||
# weird hack to record operator
|
||||
start = ts.pos()
|
||||
@@ -84,142 +68,67 @@ class CustomParser(Parser):
|
||||
)
|
||||
else:
|
||||
operator = self._parse_operator(ts)
|
||||
while ts.type() == TOK_BACKSLASH_NEWLINE:
|
||||
ts.next()
|
||||
op2 = self._parse_expression(ts)
|
||||
expr = BinaryOp(op1, operator, op2, pos=op1.pos, end_pos=op2.end_pos)
|
||||
|
||||
if ts.type() != TOK_RPAREN and ts.value() not in {":", ","}:
|
||||
if ts.type() not in (
|
||||
TOK_RPAREN,
|
||||
TOK_BACKSLASH_NEWLINE,
|
||||
) and ts.value() not in {":", ","}:
|
||||
ts.expect(TOK_EOF, message="expected end of expression", pos=ts.pos())
|
||||
|
||||
return expr
|
||||
|
||||
@_strip_ws
|
||||
def _parse_operand(self, ts):
|
||||
if ts.type() == TOK_DOLLAR:
|
||||
return self.parse_var_sub(ts)
|
||||
if ts.type() == TOK_QUOTE:
|
||||
return self.parse_quoted_word(ts)
|
||||
if ts.type() == TOK_LBRACE:
|
||||
return self.parse_braced_word(ts)
|
||||
if ts.type() == TOK_LBRACKET:
|
||||
return self.parse_command_sub(ts)
|
||||
if ts.type() == TOK_LPAREN:
|
||||
start = ts.pos()
|
||||
ts.next()
|
||||
expr = self._parse_expression(ts)
|
||||
ts.expect(
|
||||
TOK_RPAREN,
|
||||
message="reached EOF without finding match for paren",
|
||||
pos=expr.pos,
|
||||
)
|
||||
end = ts.pos()
|
||||
return ParenExpression(expr, start, end)
|
||||
if ts.value() in {"-", "+", "~", "!"}:
|
||||
operator_val = ts.value()
|
||||
operator_pos = ts.pos()
|
||||
ts.next()
|
||||
operator = BareWord(operator_val, pos=operator_pos, end_pos=ts.pos())
|
||||
operand = self._parse_operand(ts)
|
||||
# Since _parse_operand() munches whitespace after the operand, we
|
||||
# set the end of the UnaryOp to the end of the operand rather than
|
||||
# ts.pos(). Otherwise, the bounds of the UnaryOp would include all
|
||||
# that whitespace.
|
||||
return UnaryOp(operator, operand, pos=operator_pos, end_pos=operand.end_pos)
|
||||
|
||||
# If none of these, collect tokens that may comprise an operand
|
||||
operand = ""
|
||||
operand_pos = ts.pos()
|
||||
|
||||
# First, we want to check for numeric operands (either ints or numeric
|
||||
# floats) by consuming tokens as long as they comprise the prefix of a
|
||||
# numeric operand
|
||||
while ts.type() != TOK_EOF and (
|
||||
_is_int_prefix(operand + ts.value())
|
||||
or _is_float_prefix(operand + ts.value())
|
||||
):
|
||||
operand += ts.value()
|
||||
ts.next()
|
||||
|
||||
# Next, we check if we've consumed an entire numeric literal. If so, we
|
||||
# move on. If not, we keep consuming tokens that may correspond to a
|
||||
# valid bareword (pretty much just alphanumeric chars).
|
||||
if not (_is_int_literal(operand) or _is_float_literal(operand)):
|
||||
while ts.type() in {TOK_ALPHA_CHARS, TOK_NUM_CHARS}:
|
||||
operand += ts.value()
|
||||
ts.next()
|
||||
|
||||
# The above method is a little hacky. Note that it doesn't parse things
|
||||
# exactly the same as Tcl. E.g. if a script includes `expr {1foo}`,
|
||||
# tclint will report an invalid operator "foo", whereas tclsh will
|
||||
# report an invalid bareword "1foo". Despite reporting them differently
|
||||
# both tools should still catch the same syntax errors, since there are
|
||||
# no legal barewords that begin with a numeric literal prefix, and tclsh
|
||||
# will stop parsing numeric operands if they're actually followed by a
|
||||
# legal operator (e.g. `expr {1eq1}` will be handled properly).
|
||||
|
||||
is_func = _is_function(operand)
|
||||
|
||||
if not (
|
||||
_is_int_literal(operand)
|
||||
or _is_float_literal(operand)
|
||||
or _is_bool_literal(operand)
|
||||
or is_func
|
||||
):
|
||||
raise TclSyntaxError(
|
||||
f"invalid bareword in expression: {operand}", operand_pos, ts.pos()
|
||||
)
|
||||
|
||||
node = BareWord(operand, pos=operand_pos, end_pos=ts.pos())
|
||||
|
||||
if is_func:
|
||||
node = self._parse_function(ts, node)
|
||||
|
||||
return node
|
||||
|
||||
def parse_braced_word(self, ts):
|
||||
self.debug(f"parse_braced_word({ts.current})")
|
||||
def _parse_operator(self, ts):
|
||||
pos = ts.pos()
|
||||
|
||||
ts.lexer.push_state(STATE_BRACEDWORD)
|
||||
# hacky logic to handle parsing legal operators
|
||||
|
||||
ts.assert_(TOK_LBRACE)
|
||||
|
||||
word = ""
|
||||
expected_braces = [pos] # Stack für geschachtelte Klammern
|
||||
|
||||
while True:
|
||||
toktype = ts.type()
|
||||
if toktype == TOK_EOF:
|
||||
raise TclSyntaxError(
|
||||
"reached EOF without finding match for brace",
|
||||
expected_braces[-1],
|
||||
ts.pos(),
|
||||
)
|
||||
|
||||
if toktype == TOK_BACKSLASH_NEWLINE:
|
||||
# TCL-spezifisch: Zeilenumbruch mit Backslash ignorieren
|
||||
ts.next()
|
||||
continue
|
||||
|
||||
if toktype == TOK_LBRACE:
|
||||
expected_braces.append(ts.pos())
|
||||
elif toktype == TOK_RBRACE:
|
||||
try:
|
||||
expected_braces.pop()
|
||||
except IndexError:
|
||||
start = ts.pos()
|
||||
ts.next()
|
||||
end = ts.pos()
|
||||
raise TclSyntaxError(
|
||||
"found closing brace without matching open brace", start, end
|
||||
)
|
||||
|
||||
if len(expected_braces) == 0:
|
||||
ts.lexer.pop_state()
|
||||
ts.next()
|
||||
break
|
||||
|
||||
word += ts.value()
|
||||
# Skip any backslash-newlines before the operator
|
||||
while ts.type() in {TOK_WS, TOK_BACKSLASH_NEWLINE, TOK_NEWLINE}:
|
||||
ts.next()
|
||||
|
||||
end_pos = ts.pos()
|
||||
return BracedWord(word, pos=pos, end_pos=end_pos)
|
||||
if ts.value() in {"&&", "and"}: # Add explicit handling for logical AND
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
return BareWord(operator, pos=pos, end_pos=ts.pos())
|
||||
elif ts.value() in {"*", "&", "|"}:
|
||||
# one or two of these characters are legal operators
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
if ts.value() == operator:
|
||||
operator += ts.value()
|
||||
ts.next()
|
||||
elif ts.value() in {"<", ">"}:
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
if ts.value() in {operator, "="}:
|
||||
operator += ts.value()
|
||||
ts.next()
|
||||
elif ts.value() in {"=", "!"}:
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
if ts.value() != "=":
|
||||
raise TclSyntaxError(
|
||||
f"invalid operator in expression: {operator}", pos, ts.pos()
|
||||
)
|
||||
operator += ts.value()
|
||||
ts.next()
|
||||
elif ts.value() in {"*", "/", "%", "+", "-", "^", "eq", "ne", "in", "ni"}:
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
else:
|
||||
while ts.type() in {TOK_WS, TOK_BACKSLASH_NEWLINE, TOK_NEWLINE}:
|
||||
ts.next()
|
||||
|
||||
if ts.value() in {"&&", "and"}: # Try again after whitespace
|
||||
operator = ts.value()
|
||||
ts.next()
|
||||
else:
|
||||
raise TclSyntaxError(
|
||||
f"invalid operator in expression: {ts.value()}", pos, ts.pos()
|
||||
)
|
||||
|
||||
return BareWord(operator, pos=pos, end_pos=ts.pos())
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import enum
|
||||
from typing import List
|
||||
from tclint.syntax_tree import Visitor
|
||||
from tclint.syntax_tree import Visitor, QuotedWord, Command, BareWord
|
||||
from tclint.commands import get_commands
|
||||
import attrs
|
||||
from common.load_data import standard_items
|
||||
from tools.completion_items import completion
|
||||
|
||||
|
||||
class TokenModifier(enum.IntFlag):
|
||||
@@ -10,6 +12,7 @@ class TokenModifier(enum.IntFlag):
|
||||
readonly = enum.auto()
|
||||
defaultLibrary = enum.auto()
|
||||
definition = enum.auto()
|
||||
declaration = enum.auto()
|
||||
|
||||
|
||||
@attrs.define
|
||||
@@ -30,6 +33,8 @@ TOKEN_TYPES = [
|
||||
"parameter",
|
||||
"type",
|
||||
"class",
|
||||
"string",
|
||||
"parameter",
|
||||
]
|
||||
|
||||
|
||||
@@ -39,26 +44,52 @@ class _Highlighter(Visitor):
|
||||
self._tokens = []
|
||||
self.log_to_output = log_to_output
|
||||
|
||||
def visit_command(self, command):
|
||||
def visit_quoted_word(self, word: QuotedWord):
|
||||
if not word.contents:
|
||||
return
|
||||
line, col = word.contents_pos
|
||||
self._tokens.append(((line - 1, col - 1), len(word.contents), "string", []))
|
||||
pass
|
||||
|
||||
def visit_bare_word(self, word: BareWord):
|
||||
if any(item.label == word.value for item in standard_items.nx_procs) or any(
|
||||
item.label == word.value for item in completion.custom_functions
|
||||
):
|
||||
line, col = word.pos
|
||||
self._tokens.append(
|
||||
(((line - 1, col - 1), len(word.value), "function", []))
|
||||
)
|
||||
|
||||
def visit_command(self, command: Command):
|
||||
routine = command.routine
|
||||
self.log_to_output(str(command.routine))
|
||||
if routine.contents in self._commands:
|
||||
line, col = routine.pos
|
||||
self._tokens.append(((line - 1, col - 1), len(routine.contents), "keyword"))
|
||||
|
||||
if routine.contents == "set" and command.args:
|
||||
first_arg = command.args[0]
|
||||
if hasattr(first_arg, "pos") and hasattr(first_arg, "value"):
|
||||
line, col = first_arg.pos
|
||||
self._tokens.append(
|
||||
(((line - 1, col - 1), len(first_arg.value), "variable"))
|
||||
(
|
||||
(
|
||||
(line - 1, col - 1),
|
||||
len(first_arg.value),
|
||||
"variable",
|
||||
[TokenModifier.declaration],
|
||||
)
|
||||
)
|
||||
)
|
||||
if routine.contents == "proc" and command.args:
|
||||
first_arg = command.args[0]
|
||||
if hasattr(first_arg, "pos") and hasattr(first_arg, "value"):
|
||||
line, col = first_arg.pos
|
||||
self._tokens.append(
|
||||
(((line - 1, col - 1), len(first_arg.value), "function"))
|
||||
(
|
||||
(
|
||||
(line - 1, col - 1),
|
||||
len(first_arg.value),
|
||||
"function",
|
||||
[TokenModifier.declaration],
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if len(command.args) >= 2:
|
||||
@@ -71,7 +102,12 @@ class _Highlighter(Visitor):
|
||||
if hasattr(child, "value") and child.value is not None:
|
||||
line, col = child.pos
|
||||
self._tokens.append(
|
||||
((line - 1, col - 1), len(child.value), "variable")
|
||||
(
|
||||
(line - 1, col - 1),
|
||||
len(child.value),
|
||||
"parameter",
|
||||
[TokenModifier.declaration],
|
||||
)
|
||||
)
|
||||
|
||||
# Parameter mit Default-Wert ist meist eine List (z. B. {arg default})
|
||||
@@ -85,7 +121,8 @@ class _Highlighter(Visitor):
|
||||
(
|
||||
(line - 1, col - 1),
|
||||
len(name_node.value),
|
||||
"variable",
|
||||
"parameter",
|
||||
[TokenModifier.declaration],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -94,7 +131,7 @@ class _Highlighter(Visitor):
|
||||
if hasattr(first_arg, "pos") and hasattr(first_arg, "value"):
|
||||
line, col = first_arg.pos
|
||||
self._tokens.append(
|
||||
(((line - 1, col - 1), len(first_arg.value), "class"))
|
||||
(((line - 1, col - 1), len(first_arg.value), "class", []))
|
||||
)
|
||||
|
||||
def visit_var_sub(self, var_sub):
|
||||
@@ -108,35 +145,15 @@ class _Highlighter(Visitor):
|
||||
tokens = []
|
||||
last_line = 0
|
||||
last_col = 0
|
||||
for (line, col), length, tok_type in sorted(self._tokens, key=lambda x: x[0]):
|
||||
for (line, col), length, tok_type, tok_modifier in sorted(
|
||||
self._tokens, key=lambda x: x[0]
|
||||
):
|
||||
line_delta = line - last_line
|
||||
col_delta = col
|
||||
if line == last_line:
|
||||
col_delta -= last_col
|
||||
|
||||
tokens.append(Token(line_delta, col_delta, length, tok_type))
|
||||
tokens.append(Token(line_delta, col_delta, length, tok_type, tok_modifier))
|
||||
last_line, last_col = line, col
|
||||
|
||||
return tokens
|
||||
|
||||
|
||||
# @server.feature(
|
||||
# lsp.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL,
|
||||
# lsp.SemanticTokensLegend(token_types=["keyword"], token_modifiers=[]),
|
||||
# )
|
||||
# def semantic_tokens(ls: TclspServer, params: lsp.SemanticTokensParams):
|
||||
# logging.debug("Received %s: %s", lsp.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, params)
|
||||
# document = ls.workspace.get_text_document(params.text_document.uri)
|
||||
|
||||
# path = Path(document.path)
|
||||
# root = ls.get_root(path)
|
||||
# config = ls.get_config(path, root)
|
||||
|
||||
# plugins = [config.commands] if config.commands is not None else []
|
||||
# parser = Parser(command_plugins=plugins)
|
||||
# hl = _Highlighter(plugins)
|
||||
|
||||
# tree = parser.parse(document.source)
|
||||
# tree.accept(hl, recurse=True)
|
||||
|
||||
# return lsp.SemanticTokens(data=hl.tokens())
|
||||
|
||||
+93
-4
@@ -1,6 +1,95 @@
|
||||
|
||||
set main 1
|
||||
if {$main == 1 \
|
||||
&& 1 == 1} {
|
||||
if {$main == 1 && 1 == 1} {
|
||||
puts "main"
|
||||
} {}
|
||||
}
|
||||
|
||||
proc test {} {
|
||||
puts "main"
|
||||
}
|
||||
LIB_GE_command_buffer_edit_insert MOM_tool_change_LIB TOOL_CHANGE_AUTO {CUSTOM_after_tool_change_call} mytag after @TOOL_CHANGE_AUTO
|
||||
|
||||
MOM_abort
|
||||
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# Function to output a spacer line or empty line
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_spacer_output {type {length 20} {line_num 0} {output 1} check} {
|
||||
LIB_GE_message [string repeat $type $length] "output_$output" $line_num
|
||||
}
|
||||
|
||||
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# Function to delete the file
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_remove_file {file} {
|
||||
if {![SERVICE_check_file_exists $file]} {return}
|
||||
MOM_remove_file $file
|
||||
}
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# Function to check if the file exists
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_check_file_exists {file} {
|
||||
if {[file exists $file]} {return 1}
|
||||
return 0
|
||||
}
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# Ask UDE Info for the Tool
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_ask_ude_tool {pos ude_name tool_name} {
|
||||
MOM_ask_ude_info $tool_name "tool" $pos
|
||||
|
||||
if {[lsearch $::mom_result $ude_name] != -1} {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# Ask UDE Info for the Operation
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_ask_ude_operation {pos ude_name path_name} {
|
||||
MOM_ask_ude_info $path_name "operation" $pos
|
||||
|
||||
if {[lsearch $::mom_result $ude_name] != -1} {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# output suppress or dont suppress
|
||||
# [SERVICE_output_handling "ingore_output"] ignores the output
|
||||
# arg options: ingore_output
|
||||
# restore
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_output_handling {handler} {
|
||||
set ::lib_ge(hidden_output) $handler
|
||||
}
|
||||
|
||||
#_________________________________________________________________________________________________
|
||||
# <Documentation>
|
||||
# write the mom_tool_data to store tool information
|
||||
# this function is called in start of program
|
||||
#_________________________________________________________________________________________________
|
||||
proc SERVICE_get_tool_data {} {
|
||||
global mom_tool_data
|
||||
global mom_operation_info
|
||||
|
||||
set mom_tool_data(toollist) ""
|
||||
set operations $::mom_operation_name_list
|
||||
foreach operation $operations {
|
||||
if {[lsearch -exact $mom_tool_data(toollist) $mom_operation_info($operation,tool_name)] == -1} {
|
||||
lappend mom_tool_data(toollist) $mom_operation_info($operation,tool_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user