Code Comments

Programming Forum and web based access to our favorite programming groups.
For Programmers: Free Programming Magazines | New: Database administration forum
Registration is free! Edit your profileCalendarFind other membersFrequently Asked QuestionsSearch -> 
Post New Thread











Thread
Author

[OT] My First C# (warning - long post)
Here 'tis.  It looks like there's a little word-wrapping going on - I
wasn't really attentive to ensuring that I didn't go past 80 on some lines.

What this does...
- Counts lines of code, along with "executable" and "commented" lines
- Creates a cross-reference between programs and procs (copybooks).
All our procs are named Annn-something (where A is a letter and nnn is a
three-digit number).  For programs, we parse copy statements, and for
procs, we parse perform statements.  (This gives us the ability, from
our CM system, to generate a list of proc dependencies.)
- Creates a cross-reference between programs/procs and reject codes.
The system we support uses a table of reject codes with associate
narratives.  When a code is changed, all program owners who are affected
must sign off.  This xref enables that, as well as finding rejects that
are not used by any programs - these numbers can be reused.
- Creates a cross-references between programs/procs and called
procedures.  It can be used for many different things.
- [TODO] Creates a cross-reference between programs/procs and database
records/tables and fields/columns.  (This is the missing "cull" stuff.)

Some notes as well...
- the "cull" stuff isn't done yet, so if the method has "cull" in the
name, ignore it.  (There are a few utility methods under the cull stuff.)
- I've replaced our server names and passwords with placeholders, for
obvious reasons.
- I really, REALLY, *REALLY* dislike the auto-formatting that VS2005
does with putting the braces on the line under the declaration.
However, that's our shop standard, so that's what this looks like.
- I've tried to comment things as I go along, but this isn't a
finished product.  If you see a spot where more comments would be
helpful, feel free to identify them to me...
- Having to have a "break" after the "default" case on a switch is
BS...  but I digress...

Here we go - 824 lines....

-8<-----

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Text;

namespace CodeStats
{
public class CodeStatistics
{
// Properties (public instance variables)
bool    updatedStats  = false;
String  elementId     = "";
int     locTotal      = 0;
int     locExecutable = 0;
int     locCommented  = 0;

// Private instance variables
protected SqlConnection dbConn;
protected SqlConnection dbHelp;
protected char          elementType    = ' ';
protected String        elementSubType = "";
protected String        fileName       = "";
protected bool          inComment      = false;
protected List<String>  programID      = new List<String>();
protected String[]      cobolKeywords =
{"ACCEPT","ACCESS","ACQUIRE","ADD","ADVANCING","AFTER","ALL",
"ALPHABET","ALPHABETIC","ALPHABETIC-LOWER","ALPHABETIC-UPPER",

"ALPHANUMERIC","ALPHANUMERIC-EDITED","ALSO","ALTER","ALTERNATE",

"AND","ANY","APPLY","ARE","AREA","AREAS","ASCENDING","ASSIGN","AT",
"AUTHOR","BEFORE","BINARY","BINARY-1","BIT","BLANK","BLOCK",
"BOTTOM","BY","BYTE-I18N","CALL","CANCEL","CD","CF","CH",
"CHARACTER","CHARACTERS","CLASS","CLASS-NAME","CLOCK-UNITS",
"CLOSE","COBOL","CODE","CODE-SET","COLLATING","COLUMN","COMMA",
"COMMON","COMMON-STORAGE","COMMUNICATION","COMP","COMP-1",
"COMP-2","COMPUTATIONAL","COMPUTATIONAL-1","COMPUTATIONAL-2",

"COMPUTE","CONFIGURATION","CONTAINS","CONTENT","CONTINUE","CONTROL",
"CONTROLS","CONVERTING","COPY","CORR","CORRESPONDING","COUNT",
"CURRENCY","DATA","DATE","DATE-COMPILED","DATE-WRITTEN","DAY",
"DAY-OF-WEEK","DE","DEBUG-CONTENTS","DEBUG-ITEM","DEBUG-LINE",
"DEBUG-NAME","DEBUG-SUB-1","DEBUG-SUB-2","DEBUG-SUB-3",

"DEBUGGING","DECIMAL-POINT","DECLARATIVES","DELETE","DELIMITED",
"DELIMITER","DENSITY","DEPART","DEPENDING","DESCENDING",
"DESTINATION","DETAIL","DISABLE","DISP","DISP-2","DISP-I18N",
"DISPLAY","DISPLAY-2","DIVIDE","DIVISION","DOWN","DUPLICATE",
"DYNAMIC","EGI","ELSE","EMI","EMPTY","ENABLE","END","END-ADD",

"END-CALL","END-COMPUTE","END-DELETE","END-DIVIDE","END-EVALUATE",
"END-IF","END-MULTIPLY","END-OF-PAGE","END-PERFORM","END-READ",

"END-RECEIVE","END-RETURN","END-REWRITE","END-SEARCH","END-STRING",
"END-SUBTRACT","END-UNSTRING","END-WRITE","ENTER","ENTRY",
"ENVIRONMENT","EOP","EQUAL","ERROR","ESI","EVALUATE","EVERY",
"EXCEPTION","EXDEF","EXEC","EXIT","EXREF","EXTEND","EXTERNAL",

"FALSE","FD","FETCH","FILE","FILE-CONTROL","FILLER","FINAL","FIND",

"FIRST","FOOTING","FOR","FREE","FROM","FUNCTION","GENERATE","GET",

"GIVING","GLOBAL","GO","GREATER","GROUP","HEADING","HIGH-VALUE",

"HIGH-VALUES","I-O","I-O-CONTROL","IDENTIFICATION","IF","IMPART",

"IN","INDEX","INDEXED","INDICATE","INITIAL","INITIALIZE","INPUT",

"INPUT-OUTPUT","INSERT","INSPECT","INSTALLATION","INTO","INVALID",
"INVOKE","IS","JUST","JUSTIFIED","KEEP","KEY","LABEL","LAST",
"LEADING","LEFT","LENGTH","LESS","LIMIT","LIMITS","LINAGE",

"LINAGE-COUNTER","LINE","LINE-COUNTER","LINES","LINKAGE","LOCALE",

"LOCK","LOG","LOW-VALUE","LOW-VALUES","MEMORY","MERGE","MESSAGE",
"MODE","MODE-1","MODE-2","MODE-3","MODE-4","MODIFY","MODULES",

"MOVE","MULTIPLE","MULTIPLY","NATIVE","NEGATIVE","NEXT","NO","NOT",

"NUMBER","NUMERIC","NUMERIC-EDITED","OBJECT-COMPUTER","OCCURS","OF",

"OFF","OMITTED","ON","OPEN","OPTIONAL","OR","ORDER","ORGANIZATION",
"OTHER","OUTPUT","OVERFLOW","OWNER","PACKED-DECIMAL","PADDING",

"PAGE","PAGE-COUNTER","PERFORM","PF","PH","PIC","PICTURE","PLUS",
"POINTER","POINTS","POSITION","POSITIVE","PRINTING","PRIOR",

"PROCEDURE","PROCEDURES","PROCEED","PROGRAM","PROGRAM-ID","PURGE",
"QUEUE","QUOTE","QUOTES","RANDOM","RANK","RD","READ","RECEIVE",
"RECORD","RECORDING","RECORDS","REDEFINES","REEL","REFERENCE",

"REFERENCES","RELATIVE","RELEASE","REMAINDER","REMOVAL","REMOVE",
"RENAMES","REPLACE","REPLACING","REPORT","REPORTING","REPORTS",

"RERUN","RESERVE","RESET","RETURN","REVERSED","REWIND","REWRITE",

"RF","RH","RIGHT","ROUNDED","RUN","SAME","SD","SEARCH","SECTION",

"SECURITY","SEGMENT","SEGMENT-LIMIT","SELECT","SEND","SENTENCE",
"SEQUENTIAL","SET","SIGN","SIZE","SORT","SORT-MERGE","SOURCE",
"SOURCE-COMPUTER","SPACE","SPACES","SPECIAL-NAMES","STANDARD",

"STANDARD-1","STANDARD-2","START","STATUS","STOP","STORE","STRING",
"SUB-QUEUE-1","SUB-QUEUE-2","SUB-QUEUE-3","SUBTRACT","SUM",
"SUPPRESS","SYMBOLIC","SYNC","SYNCHRONIZED","TABLE","TALLYING",
"TAPE","TERMINAL","TERMINATE","TEST","TEXT","THAN","THEN",

"THROUGH","THRU","TIME","TIMES","TO","TOP","TRAILING","TRUE","TYPE",

"UNIT","UNSTRING","UNTIL","UP","UPON","USAGE","USE","USING","VALUE",

"VALUES","VARYING","WHEN","WITH","WORDS","WORKING-STORAGE","WRITE",

"ZERO","ZEROES","ZEROS","+","-","*","/","**",">","<","=",">=","<="};

// Constuctor for no parameter
public CodeStatistics(String csServerName)
{
openSqlConnection(csServerName);
}

// Constructor for passed Element ID
public CodeStatistics(String csServerName, String csElementId)
{
openSqlConnection(csServerName);
retrieveElementInfo(csElementId);
}

// Establish the element for this class instance
public void retrieveElementInfo(String reiElementId)
{
// Retrieve the information about the passed program
SqlCommand cmd = new SqlCommand("SELECT element_id,
element_type, element_subtype, server_name "
+ "FROM active_elements "
+ "WHERE element_id = '" + reiElementId.Trim() + "'",
dbConn);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
elementType    =
Convert.ToChar(dr["element_type"].ToString().Trim().Substring(0,1));
elementSubType = dr["element_subtype"].ToString().Trim();
fileName       = dr["server_name"].ToString().Trim();
elementId      = reiElementId;
}
dr.Close();
dr.Dispose();
}

// Update the statistics for the element ID
public void updateStatistics(String usPath, String usProcessName)
{
if (File.Exists(usPath + fileName))
{
String textLine = "";

// Depending on the type, clear out the cross-reference
tables
switch (elementType)
{
case 'P':
case 'L':
SqlCommand scDel = new SqlCommand();
scDel.Connection = dbConn;

// Delete item/proc xref
scDel.CommandText = "DELETE FROM Proc_Prog_Xref
WHERE ProgName = '" + elementId + "'";
scDel.ExecuteNonQuery();

// Delete item/reject xref
scDel.CommandText = "DELETE FROM RejectsXref
WHERE program = '" + elementId + "'";
scDel.ExecuteNonQuery();

// Delete item/call xref
scDel.CommandText = "DELETE FROM
sdp_CSCI_Call_Xref WHERE Element_ID = '" + elementId + "'";
scDel.ExecuteNonQuery();

// Delete cull information
scDel.CommandText = "DELETE FROM
sdp_Dbe_Csci_Xref WHERE CSCI = '" + elementId + "'";
scDel.ExecuteNonQuery();
scDel.CommandText = "DELETE FROM
sdp_Dbr_Csci_Xref WHERE CSCI = '" + elementId + "'";
scDel.ExecuteNonQuery();

scDel.Dispose();
break;
}

StreamReader file = File.OpenText(usPath + fileName);

while (!file.EndOfStream)
{
textLine = file.ReadLine().ToUpper();

if ((elementType != 'P') && (elementType != 'L'))
{
textLine = textLine.Trim();
}

countLine(textLine); // Count this line as a "line
of code"

switch(elementType)
{
case 'P':
case 'L':
textLine = textLine.Replace(",", "
").Replace(".", " ").Trim();
updateProcXref(textLine);
updateRejectXref(textLine, usProcessName);
updateCallXref(textLine);
//updateCull(textLine);
break;
}

}

file.Close();
file.Dispose();

if (programID.Count > 0)
{   // Delete any references to calls if the target is
defined in the program (i.e., nested subprograms)
SqlCommand scDelete = new SqlCommand();

scDelete.CommandText = "DELETE FROM
sdp_CSCI_CALL_Xref "
+ "WHERE Element_ID = '" + elementId + "' "
+ "AND Call_Name IN ('";
for (int i = 0; i < programID.Count; i++)
{
scDelete.CommandText += programID[i] + "'";
if (i < (programID.Count - 1))
{
scDelete.CommandText += ",'";
}
}
scDelete.CommandText += ")";
scDelete.Connection = dbConn;
scDelete.ExecuteNonQuery();
scDelete.Dispose();
}

// Update LOC in the CSCS database
SqlCommand sc = new SqlCommand("UPDATE Active_Elements "
+ "SET   Commented_Lines  = " +
locCommented.ToString()
+ ", Executable_Lines = " +
locExecutable.ToString()
+ ", Total_Lines      = " + locTotal.ToString()
+ "WHERE Element_ID = '" + elementId + "'", dbConn);
sc.ExecuteNonQuery();
sc.Dispose();
}
}

protected void countLine(String clLine)
{
String commentStart  = "";
String commentEnd    = "";
String commentSingle = "";

// A line is a line...
locTotal++;

if (clLine != "")
{
switch(elementType)
{
case 'P':
case 'L':
// COBOL
if ((clLine.Length > 6) &&
(clLine.Substring(6,1) == "*"))
{
locCommented++;
}
else
{
locExecutable++;
}
break;

case 'G':
// GUI
if ((elementSubType == "HTML") ||
(elementSubType == "CSS") || (elementSubType == "XML"))
{
commentStart = "<!--";
commentEnd   = "-->";
}
else
{
if (elementSubType == "XSLT")
{
commentStart = "<xsl:comment>";
commentEnd   = "</xsl:comment>";
}
else
{
if (elementSubType == "JS")
{
commentStart  = "/*";
commentEnd    = "*/";
commentSingle = "//";
}
}
}

if ((commentStart == "") && (commentEnd == "")
&& (commentSingle == ""))
{   // We don't look for comments - if it's not
blank, it's executable
locExecutable++;
}
else
{
if (inComment)
{   // We're in a multi-line comment
locCommented++;
if (clLine.IndexOf(commentEnd) >= 0)
{   // This is the last line of the
multi-line comment
inComment = false;
}
}
else
{
if (clLine.IndexOf(commentStart) >= 0)
{
if (clLine.IndexOf(commentEnd) == -1)
{   // Start of a multi-line comment
inComment = true;
}
if ((clLine.IndexOf(commentStart)
== 0))
{   // Nothing before the comment -
the entire line is commented
locCommented++;
}
else
{   // Something before the comment
- count the line as executable
locExecutable++;
}
}
else
{
if ((commentSingle != "") &&
(clLine.IndexOf(commentSingle) >= 0))
{
if
(clLine.IndexOf(commentSingle) == 0)
{   // The entire line is a comment
locCommented++;
}
else
{   // Only the end of the line
is commented
locExecutable++;
}
}
else
{
locExecutable++;
}
}
}
}
break;

case 'R':
// Runstreams
if ((elementSubType == "IPF") &&
(clLine.Substring(0,1) == "@"))
{   // IPF comment character
locCommented++;
}
else
{
if ((elementSubType == "QLP") &&
(clLine.Substring(0,1) == "*"))
{   // QLP comment character
locCommented++;
}
else
{   // Apply ECL comment rules
if ((clLine.Length > 2) &&
((clLine.Substring(0,3) == "@ .") || (clLine.Substring(0,3) == "@. ")))
{   // ECL comment character
locCommented++;
}
else
{
locExecutable++;
}
}
}
break;

case 'Q':
// IQ/U Runstreams
if (clLine.Substring(0,1) == ".")
{
locCommented++;
}
else
{
locExecutable++;
}
break;

default:
// Anything else, a non-blank line is executable
locExecutable++;
break;
}
}
}

protected void updateProcXref(String upxLine)
{
// For this to work right, we need all items separated by
only one space
upxLine = normalizeSpace(upxLine);

switch (elementType)
{
case 'P':
// Establish the cross-reference based on copy
statement
if ((upxLine.Length > 6) && (upxLine.Substring(0,5)
== "COPY "))
{
String[] words  = upxLine.Split(' ');
String[] pieces = words[1].Split('-');

if (isElement(pieces[0]))
{   // See if this is already in the
cross-reference
SqlCommand scCheck = new SqlCommand("SELECT
ProgName FROM Proc_Prog_Xref "
+ "WHERE   ProgName   = '" + elementId
+ "' "
+ "AND ProcName   = '" + pieces[0]
+ "' "
+ "AND EntryPoint = '" + words[1]
+ "'", dbConn);
SqlDataReader drCheck =
scCheck.ExecuteReader();
if (!drCheck.HasRows)
{   // Add this program/proc to the table
executeSQL("INSERT INTO Proc_Prog_Xref "
+ "(ProgName, ProcName, Passive,
EntryPoint) "
+ "VALUES ('" + elementId + "','" +
pieces[0] + "',0,'" + words[1] + "')");
}
drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();
}
}
break;

case 'L':
// Establish the cross-reference based on perform
statement
if ((upxLine.Length > 9) && (upxLine.Substring(0,8)
== "PERFORM "))
{
String[] words  = upxLine.Split(' ');
String[] pieces = words[1].Split('-');

// Don't count performs of the proc itself
if ((pieces[0] != elementId) &&
(isElement(pieces[0])))
{   // See if this is already in the xref
SqlCommand scCheck = new SqlCommand("SELECT
ProgName FROM Proc_Prog_Xref "
+ "WHERE ProgName = '" + elementId + "' "
+ "AND ProcName = '" + pieces[0] +
"'", dbConn);
SqlDataReader drCheck =
scCheck.ExecuteReader();
if (!drCheck.HasRows)
{
executeSQL("INSERT INTO Proc_Prog_Xref "
+ "(ProgName, ProcName, Passive,
EntryPoint) "
+ "VALUES ('" + elementId + "','" +
pieces[0] + "',1,NULL)");
}
drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();
}
}
break;
}
}

protected void updateRejectXref(String urxLine, String
urxProcessName)
{
Int32 rejectCode;

// Get rid of extra spaces
urxLine = normalizeSpace(urxLine);

if ((urxLine.IndexOf("REJCDE") >= 0) &&
(urxLine.IndexOf("MOVE ") >= 0))
{   // Line is "MOVE [something] TO REJCDE"
String[] words = urxLine.Split(' ');
if (Int32.TryParse(words[1], out rejectCode))
{
// Mask off narratives to get the lowest 4 digits
rejectCode = rejectCode % 10000;

if (rejectCode > 0)
{   // Is this reject already in the xref?
SqlCommand scCheck = new SqlCommand("SELECT
program FROM RejectsXref "
+ "WHERE program = '" + elementId + "' "
+ "AND reject_num = " +
rejectCode.ToString(), dbConn);
SqlDataReader drCheck = scCheck.ExecuteReader();
if (!drCheck.HasRows)
{   // Insert it
executeSQL("INSERT INTO RejectsXref "
+ "(program, reject_num, last_updated,
last_updated_by) "
+ "VALUES ('" + elementId + "'," +
rejectCode.ToString()
+ ",current_timestamp,'" +
urxProcessName + "')");
}
drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();
}
}
}
}

protected void updateCallXref(String ucxLine)
{
String[] words = normalizeSpace(ucxLine).Split(' ');

// Check for "PROGRAM-ID"
if (words[0] == "PROGRAM-ID")
{   // Save these off - we'll delete them at the end
programID.Add(words[1]);
}

if ((words.Length > 1) && (words[0] == "CALL"))
{
if ((words[1].Substring(0,1) == "\"") ||
(words[1].Substring(0,1) == "'"))
{   // Calling a literal - this is one we'll store
String callName =
words[1].Substring(1,words[1].Length - 2);

SqlCommand scCheck = new SqlCommand("SELECT
Element_ID FROM sdp_CSCI_CALL_Xref "
+ "WHERE Element_ID = '" + elementId + "' "
+ "AND Call_Name = '" + callName + "'",
dbConn);
SqlDataReader drCheck = scCheck.ExecuteReader();
if (!drCheck.HasRows)
{   // It's not there - insert it
executeSQL("INSERT INTO sdp_CSCI_CALL_Xref "
+ "(Element_ID, Call_Name) "
+ "VALUES ('" + elementId + "','" +
callName + "')");
}
drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();
}
}
}

protected void updateCull(String ucLine)
{
ucLine = normalizeSpace(ucLine);

if (   (ucLine.IndexOf("FETCH ")  >= 0) ||
(ucLine.IndexOf("FIND ")   >= 0)
|| (ucLine.IndexOf("MODIFY ") >= 0) ||
(ucLine.IndexOf("STORE ")  >= 0)
|| (ucLine.IndexOf("DELETE ") >= 0) ||
(ucLine.IndexOf("INSERT ") >= 0)
|| (ucLine.IndexOf("REMOVE ") >= 0))
{
updateCullRecord(ucLine);
}
else
{
// Split up the words, and check for a DMS field name
or R-proc data name
String[] words = ucLine.Split(' ');
for (int i = 0; i < words.Length; i++)
{
if ((!isCobolKeyword(words[i])) &&
(!hasSymbols(words[i])))
{
updateCullItem(words[i], ucLine);
}
}
}
}

// Update DML records in cull
protected void updateCullRecord(String ucrLine)
{
String[] words  = ucrLine.Split(' ');
Int32    word   = 0;
String   column = "";

// --- CHECK #1 --- record name //

// Find the word where we're doing the DML
while ((words[word] != "FETCH")  && (words[word] != "FIND")
&& (words[word] != "MODIFY") && (words[word] != "STORE")
&& (words[word] != "DELETE") && (words[word] != "INSERT")
&& (words[word] != "REMOVE") && (word < words.Length))
{
word++;
}

if ((word < (words.Length - 2))
&& ((   words[word + 1] == "FIRST") || (words[word + 1]
== "NEXT")
|| (words[word + 1] == "PRIOR") || (words[word + 1]
== "LAST")))
{   // "FETCH FIRST xxx", etc.
word++;
}

if ((word < (words.Length - 2)) && (words[word + 1] !=
"RECORD"))
{
// Determine the proper column name
if ((words[word] == "FETCH") || (words[word] == "FIND"))
{
column = "Fetches";
}
else
{
if (words[word] == "MODIFY")
{
column = "Modifies";
}
else
{
column = words[word].ToLower() + "s";
}
}

// The next word may be a record name
String recordName = words[++word];

// Is this name a valid record?
SqlCommand scRecChk = new SqlCommand("SELECT
record_name FROM dms_records "
+ "WHERE record_name = '" + recordName + "'", dbHelp);
SqlDataReader drRecChk = scRecChk.ExecuteReader();

if (drRecChk.HasRows)
{   // Does the record already exist in the
cross-reference?
SqlCommand scCheck = new SqlCommand("SELECT CSCI
FROM sdp_Dbr_Csci_Xref "
+ "WHERE Dbr = '" + recordName + "' "
+ "AND Csci = '" + elementId + "'", dbConn);
SqlDataReader drCheck = scCheck.ExecuteReader();

if (!drCheck.HasRows)
{   // Add a new zeroed-out row
SqlCommand scInsert = new SqlCommand("INSERT
INTO sdp_Dbr_Csci_Xref "
+ "(Dbr, Csci, Fetches, Modifies, Inserts,
Stores, Removes, Deletes) "
+ "VALUES ('" + recordName + "','" +
elementId + "',0,0,0,0,0,0)", dbConn);
scInsert.ExecuteNonQuery();
scInsert.Dispose();
}

drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();

// Update this count
SqlCommand scUpdate = new SqlCommand("UPDATE
sdp_Dbr_Csci_Xref "
+ "SET " + column + " = " + column + " + 1 "
+ "WHERE Dbr = '" + recordName + "' "
+ "AND Csci = '" + elementId + "'", dbConn);
scUpdate.ExecuteNonQuery();
scUpdate.Dispose();
}

drRecChk.Close();
drRecChk.Dispose();
scRecChk.Dispose();
}

// --- CHECK #2 --- set name //

if ((ucrLine.IndexOf(" SET") >= 0) || (ucrLine.IndexOf("VIA
") >= 0))
{
String setName = "";

// Find the word "via" or "set"
word = 0;
while ((words[word] != "VIA") && (words[word] != "SET"))
{
word++;
}

if ((words[word] == "SET") && (word > 0))
{   // "FETCH xxx WITHIN xxxx SET", "REMOVE xxxx FROM
xxxxx SET", etc.
setName = words[--word];
}
else
{
if ((words[word] == "VIA") && (word < (words.Length
-1)))
{   // "FETCH xxx VIA xxxx USING xxxx" format statement
setName = words[++word];
}
}

if (setName != "")
{
// Is this a valid set name?
SqlCommand scSetChk = new SqlCommand("SELECT
set_name FROM dms_sets "
+ "WHERE set_name = '" + setName + "'", dbHelp);
SqlDataReader drSetChk = scSetChk.ExecuteReader();

if (drSetChk.HasRows)
{
// What column name do we update?
column = "";

if ((ucrLine.IndexOf("FETCH ") >= 0) ||
(ucrLine.IndexOf("FIND ") >= 0))
{   column = "Fetches";
}
else
{   if (ucrLine.IndexOf("INSERT") >= 0)
{   column = "Inserts";
}
else
{   if (ucrLine.IndexOf("REMOVE") >= 0)
{   column = "Removes";
}
}
}

if (column != "")
{   // Does it already exist in the
cross-reference?
SqlCommand scCheck = new SqlCommand("SELECT
Dbr FROM sdp_Dbr_Csci_Xref "
+ "WHERE Dbr = '" + setName + "'", dbConn);
SqlDataReader drCheck =
scCheck.ExecuteReader();

if (!drCheck.HasRows)
{   // Insert a new blank row
SqlCommand scInsert = new
SqlCommand("INSERT INTO sdp_Dbr_Csci_Xref "
+ "(Dbr, Csci, Fetches, Modifies,
Inserts, Stores, Removes, Deletes) "
+ "VALUES ('" + setName + "','" +
elementId + "',0,0,0,0,0,0)", dbConn);
scInsert.ExecuteNonQuery();
scInsert.Dispose();
}

drCheck.Close();
drCheck.Dispose();
scCheck.Dispose();

SqlCommand scUpdate = new
SqlCommand("UPDATE sdp_Dbr_Csci_Xref "
+ "SET " + column + " = " + column + "
+ 1 "
+ "WHERE Dbr = '" + setName + "' "
+ "AND Csci = '" + elementId + "'",
dbConn);
scUpdate.ExecuteNonQuery();
scUpdate.Dispose();
}
}

drSetChk.Close();
drSetChk.Dispose();
scSetChk.Dispose();
}
}
}

protected void updateCullItem(String uciWord, String uciLine)
{
bool used    = false;
bool updated = false;

// Check to see if the word starts with "R" and has a dash,
and is not this proc
if ((uciWord.Substring(0,1) == "R") &&
(uciWord.Substring(3,1) == "-")
&& (uciWord.Substring(0,4) != elementId))
{
if (uciLine.IndexOf("PERFORM") >= 0)
{   // We've got a paragraph name performed
SqlCommand scTables = new SqlCommand("SELECT
DISTINCT table_name rt "
+ "FROM rdms_tables rt, rdms_table_columns rtc "
+ "WHERE rt.table_name = rtc.table_name "
+ "AND rtc.r_proc_element_name LIKE '" +
uciWord.Substring(0,4) + "%'",dbHelp);
SqlDataReader drTables = scTables.ExecuteReader();

while(drTables.HasRows)
{   // See if this table already exists in the cull
look-up
int i = 0; // !WORK this is crap
}
}
else
{
if (uciLine.IndexOf("MOVE") >= 0)
{
if (uciLine.IndexOf("TO") >
uciLine.IndexOf(uciWord))
{
used = true;
}
else
{
updated = true;
}
}
else
{
updated = true;
}
}
}
else
{   // See if the word is a valid DMS field
}
}

// Establish connections with the database
protected void openSqlConnection(String oscServerName)
{
String connString = "";

if (oscServerName == "") {
oscServerName = "[servername]";
}

connString = "server=" + oscServerName +
";database=[database];User ID=[user];Password=[password];";
dbConn = new SqlConnection(connString);
dbConn.Open();

connString =
connString.Replace("[database],"[another-database]");
dbHelp = new SqlConnection(connString);
dbHelp.Open();
}

public String cscsRegValue(String crvKey)
{
SqlCommand crvCmd = new SqlCommand("SELECT reg_value "
+ "FROM sdp_registry "
+ "WHERE reg_key = '" + crvKey + "'", dbConn);
SqlDataReader crvDR = crvCmd.ExecuteReader();
if (crvDR.Read())
{
return(crvDR["reg_value"].ToString().Trim());
}
else
{
return("");
}
}

protected void executeSQL(String esText)
{
SqlConnection esConn = new
SqlConnection(dbConn.ConnectionString + "password=[password];");
SqlCommand    esCmd  = new SqlCommand(esText, esConn);
esConn.Open();
esCmd.ExecuteNonQuery();
esCmd.Dispose();
esConn.Close();
esConn.Dispose();
}

// Eliminates all embedded spaces more than one
protected String normalizeSpace(String nsText)
{
String workText = nsText;

while (workText.IndexOf("  ") >= 0)
{
workText = workText.Replace("  "," ");
}
return(workText);
}

// Returns "true" if the text passed is an element in CSCS
protected bool isElement(String ieText)
{
Boolean itExists = false;

SqlCommand ieCmd = new SqlCommand("SELECT Actv_Ind FROM
Active_Elements "
+ " WHERE Element_ID = '" + ieText + "'", dbConn);
SqlDataReader ieDR  = ieCmd.ExecuteReader();
if (ieDR.HasRows) {
itExists = true;
}
ieDR.Close();
ieDR.Dispose();
ieCmd.Dispose();

return(itExists);
}

// Returns "true" if the word passed is a COBOL keyword
protected bool isCobolKeyword(String ickText)
{
Int32 i = 0;
while ((i < cobolKeywords.Length) && (ickText !=
cobolKeywords[i]))
{
i++;
}
if (i < cobolKeywords.Length)
{
return(true);
}
else
{
return(false);
}
}

// Returns "true" if the words passed has symbols in it
protected bool hasSymbols(String hsText)
{
if (   (hsText.IndexOf("(")  >= 0) || (hsText.IndexOf(")")
>= 0)
|| (hsText.IndexOf("\"") >= 0) || (hsText.IndexOf("'")
>= 0)
|| (hsText.IndexOf("_")  >= 0))
{
return(true);
}
else
{
return(false);
}
}

}
}

--
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
~   /   \  /         ~        Live from Montgomery, AL!       ~
~  /     \/       o  ~                                        ~
~ /      /\   -   |  ~          daniel@thebelowdomain         ~
~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
~ h---- r+++ z++++                                            ~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~

"Who is more irrational?  A man who believes in a God he doesn't see, or
a man who's offended by a God he doesn't believe in?" - Brad Stine

Report this thread to moderator Post Follow-up to this message
Old Post
LX-i
01-31-07 02:55 AM


Re: [OT] My First C# (warning - long post)
Hi Daniel,

Unfortunately, much as I'd like to, I'm just too busy at the moment to
analyse this properly.

Fortunately, Andrew is doing so (I had a quick look at his comments and
endorse them 100%) and one set of criticisms is probably all you need on a
first attempt :-)

I formed some first impressions from a quick look (before I saw Andrew's
comments.... :-)) and they were as follows:

1. It is a procedural translation into an OO environment. Even down to the
"Working-storage" at the top of the Class... :-)

2. You show an excellent grasp of using functions and, at the nitty-gritty
level you have it sussed. (I think you may be over-using Trim()...
"Convert.ToChar(dr["element_type"].ToString().Trim().Substring(0,1))" seems
a bit unnecessary to me, when all you are wanting is one byte, but I haven't
checked the details...:-)

3. The embedded SQL is just a hangover from procedural code; it is
inefficient and ugly.  Think in tiers; separate data access from business
logic. Treat db connections as precious; don't hold them any longer than you
need to. I posted a link previously which outlines the C# approach and it is
quite different from the procedural embedded SQL approach. (Since my own
stuff is now working, I can also confirm that it is VERY fast...)

4.  I think you are very lucky to have someone like Andrew looking at it. I
read his comments and agree almost entirely. (I think 10 lines is  a bit too
rigid a rule, but the principle is correct.). In OO, as in most online
processing, "small is beautiful"... Andrew's point about refactoring is an
excellent one and I wouldn't have thought of that as a good way to improve
what you have; I've learned from this interchange :-)

5. You deserve credit for posting ANY code here, and to post a first
attempt, is brave and  admirable. I know you won't take the comments to
heart in a negative way.

6. You might think about offloading a lot of the literals into external
data. C# provides a number of places where you can put stuff... System
collections, XML files, configuration data, to name a few. The COBOL
Reserved Word list could be an XML file that gets loaded once at startup,
rather than being embedded in the program.

I use an XML file to "remember" the last used state of an app. so the user
doesn't have to keep re-keying it if they plan on processing against the
same database... but this is only one way, and possibly not even the best.
It has the advantage that things like connection strings and static SQL can
be changed from outside the program. C# makes it a doddle to manipulate XML.

SUMMARY:

For my money, you need to start thinking in terms of a production line.
Think about a series of (small) machines (components) that take scrap metal
in one end and push knives and forks out the other. Each machine carries out
another step in the process, each machine does exactly what it does, and
functionality does not overlap. (Think encapsulation and "black boxes").
Some machines provide support functions to machines on the main line, but
for each machine, the goals it must achieve are clear, and the primary focus
for it, from which it must not be distracted by having to do ancilliary and
support functions (like accessing databases). Think of machines in each
layer (tier) of the production process. (A component needs to validate,
retrieve, or update certain data? It should focus on what it is going to DO
with that data and leave the "lower order" functions to other components who
deal with that. It can simply activate a "retriever" and know that what
comes back is valid and timely or whatever...) Activate the retriever; take
what it returns, get on with what this component is really about...:-)

The major diference between OO and procedural processing is that procedural
code tends to not even start processing until EVERYTHING is defined in data
terms, and these data definitions then drive the processing. With OO, only
the data necessary for a specific function is required at any given moment,
and the data and the manipulation of it is "encapsulated" into a specific
object.  OO objects neither know nor care what other OO Objects are doing.
They are focussed on achieving their own design goals and that is all that
matters. Communication with the outside world is by means of messages and
interfaces.

Still, you have demonstrated a really good grasp of the language itself, the
program works, and it can be made more elegant fairly easily. All in all,
pretty good for a first attempt :-)

Pete.



"LX-i" <lxi0007@netscape.net> wrote in message
 news:68bfe$45bfea28$454920f8$29351@KNOLO
GY.NET...
> Here 'tis.  It looks like there's a little word-wrapping going on - I
> wasn't really attentive to ensuring that I didn't go past 80 on some
> lines.
>
> What this does...
>  - Counts lines of code, along with "executable" and "commented" lines
>  - Creates a cross-reference between programs and procs (copybooks). All
> our procs are named Annn-something (where A is a letter and nnn is a
> three-digit number).  For programs, we parse copy statements, and for
> procs, we parse perform statements.  (This gives us the ability, from our
> CM system, to generate a list of proc dependencies.)
>  - Creates a cross-reference between programs/procs and reject codes. The
> system we support uses a table of reject codes with associate narratives.
> When a code is changed, all program owners who are affected must sign off.
> This xref enables that, as well as finding rejects that are not used by
> any programs - these numbers can be reused.
>  - Creates a cross-references between programs/procs and called
> procedures.  It can be used for many different things.
>  - [TODO] Creates a cross-reference between programs/procs and database
> records/tables and fields/columns.  (This is the missing "cull" stuff.)
>
> Some notes as well...
>  - the "cull" stuff isn't done yet, so if the method has "cull" in the
> name, ignore it.  (There are a few utility methods under the cull stuff.)
>  - I've replaced our server names and passwords with placeholders, for
> obvious reasons.
>  - I really, REALLY, *REALLY* dislike the auto-formatting that VS2005 does
> with putting the braces on the line under the declaration. However, that's
> our shop standard, so that's what this looks like.
>  - I've tried to comment things as I go along, but this isn't a finished
> product.  If you see a spot where more comments would be helpful, feel
> free to identify them to me...
>  - Having to have a "break" after the "default" case on a switch is BS...
> but I digress...
>
> Here we go - 824 lines....
>
> -8<-----
>
> using System;
> using System.Collections.Generic;
> using System.Data.SqlClient;
> using System.IO;
> using System.Text;
>
> namespace CodeStats
> {
>     public class CodeStatistics
>     {
>         // Properties (public instance variables)
>         bool    updatedStats  = false;
>         String  elementId     = "";
>         int     locTotal      = 0;
>         int     locExecutable = 0;
>         int     locCommented  = 0;
>
>         // Private instance variables
>         protected SqlConnection dbConn;
>         protected SqlConnection dbHelp;
>         protected char          elementType    = ' ';
>         protected String        elementSubType = "";
>         protected String        fileName       = "";
>         protected bool          inComment      = false;
>         protected List<String>  programID      = new List<String>();
>         protected String[]      cobolKeywords =
>             {"ACCEPT","ACCESS","ACQUIRE","ADD","ADVANCING","AFTER","ALL",
>             "ALPHABET","ALPHABETIC","ALPHABETIC-LOWER","ALPHABETIC-UPPER",
>
> "ALPHANUMERIC","ALPHANUMERIC-EDITED","ALSO","ALTER","ALTERNATE",
>
> "AND","ANY","APPLY","ARE","AREA","AREAS","ASCENDING","ASSIGN","AT",
>             "AUTHOR","BEFORE","BINARY","BINARY-1","BIT","BLANK","BLOCK",
>             "BOTTOM","BY","BYTE-I18N","CALL","CANCEL","CD","CF","CH",
>             "CHARACTER","CHARACTERS","CLASS","CLASS-NAME","CLOCK-UNITS",
>
> "CLOSE","COBOL","CODE","CODE-SET","COLLATING","COLUMN","COMMA",
>             "COMMON","COMMON-STORAGE","COMMUNICATION","COMP","COMP-1",
>             "COMP-2","COMPUTATIONAL","COMPUTATIONAL-1","COMPUTATIONAL-2",
>
> "COMPUTE","CONFIGURATION","CONTAINS","CONTENT","CONTINUE","CONTROL",
>             "CONTROLS","CONVERTING","COPY","CORR","CORRESPONDING","COUNT",
>             "CURRENCY","DATA","DATE","DATE-COMPILED","DATE-WRITTEN","DAY",
>             "DAY-OF-WEEK","DE","DEBUG-CONTENTS","DEBUG-ITEM","DEBUG-LINE",
>             "DEBUG-NAME","DEBUG-SUB-1","DEBUG-SUB-2","DEBUG-SUB-3",
>
> "DEBUGGING","DECIMAL-POINT","DECLARATIVES","DELETE","DELIMITED",
>             "DELIMITER","DENSITY","DEPART","DEPENDING","DESCENDING",
>             "DESTINATION","DETAIL","DISABLE","DISP","DISP-2","DISP-I18N",
>             "DISPLAY","DISPLAY-2","DIVIDE","DIVISION","DOWN","DUPLICATE",
>             "DYNAMIC","EGI","ELSE","EMI","EMPTY","ENABLE","END","END-ADD",
>
> "END-CALL","END-COMPUTE","END-DELETE","END-DIVIDE","END-EVALUATE",
>
> "END-IF","END-MULTIPLY","END-OF-PAGE","END-PERFORM","END-READ",
>
> "END-RECEIVE","END-RETURN","END-REWRITE","END-SEARCH","END-STRING",
>             "END-SUBTRACT","END-UNSTRING","END-WRITE","ENTER","ENTRY",
>             "ENVIRONMENT","EOP","EQUAL","ERROR","ESI","EVALUATE","EVERY",
>             "EXCEPTION","EXDEF","EXEC","EXIT","EXREF","EXTEND","EXTERNAL",
>
> "FALSE","FD","FETCH","FILE","FILE-CONTROL","FILLER","FINAL","FIND",
>
> "FIRST","FOOTING","FOR","FREE","FROM","FUNCTION","GENERATE","GET",
>
> "GIVING","GLOBAL","GO","GREATER","GROUP","HEADING","HIGH-VALUE",
>
> "HIGH-VALUES","I-O","I-O-CONTROL","IDENTIFICATION","IF","IMPART",
>
> "IN","INDEX","INDEXED","INDICATE","INITIAL","INITIALIZE","INPUT",
>
> "INPUT-OUTPUT","INSERT","INSPECT","INSTALLATION","INTO","INVALID",
>             "INVOKE","IS","JUST","JUSTIFIED","KEEP","KEY","LABEL","LAST",
>             "LEADING","LEFT","LENGTH","LESS","LIMIT","LIMITS","LINAGE",
>
> "LINAGE-COUNTER","LINE","LINE-COUNTER","LINES","LINKAGE","LOCALE",
>
> "LOCK","LOG","LOW-VALUE","LOW-VALUES","MEMORY","MERGE","MESSAGE",
>             "MODE","MODE-1","MODE-2","MODE-3","MODE-4","MODIFY","MODULES",
>
> "MOVE","MULTIPLE","MULTIPLY","NATIVE","NEGATIVE","NEXT","NO","NOT",
>
> "NUMBER","NUMERIC","NUMERIC-EDITED","OBJECT-COMPUTER","OCCURS","OF",
>
> "OFF","OMITTED","ON","OPEN","OPTIONAL","OR","ORDER","ORGANIZATION",
>
> "OTHER","OUTPUT","OVERFLOW","OWNER","PACKED-DECIMAL","PADDING",
>
> "PAGE","PAGE-COUNTER","PERFORM","PF","PH","PIC","PICTURE","PLUS",
>             "POINTER","POINTS","POSITION","POSITIVE","PRINTING","PRIOR",
>
> "PROCEDURE","PROCEDURES","PROCEED","PROGRAM","PROGRAM-ID","PURGE",
>
> "QUEUE","QUOTE","QUOTES","RANDOM","RANK","RD","READ","RECEIVE",
>             "RECORD","RECORDING","RECORDS","REDEFINES","REEL","REFERENCE",
>
> "REFERENCES","RELATIVE","RELEASE","REMAINDER","REMOVAL","REMOVE",
>
> "RENAMES","REPLACE","REPLACING","REPORT","REPORTING","REPORTS",
>
> "RERUN","RESERVE","RESET","RETURN","REVERSED","REWIND","REWRITE",
>
> "RF","RH","RIGHT","ROUNDED","RUN","SAME","SD","SEARCH","SECTION",
>
> "SECURITY","SEGMENT","SEGMENT-LIMIT","SELECT","SEND","SENTENCE",
>             "SEQUENTIAL","SET","SIGN","SIZE","SORT","SORT-MERGE","SOURCE",
>             "SOURCE-COMPUTER","SPACE","SPACES","SPECIAL-NAMES","STANDARD",
>
> "STANDARD-1","STANDARD-2","START","STATUS","STOP","STORE","STRING",
>             "SUB-QUEUE-1","SUB-QUEUE-2","SUB-QUEUE-3","SUBTRACT","SUM",
>
> "SUPPRESS","SYMBOLIC","SYNC","SYNCHRONIZED","TABLE","TALLYING",
>             "TAPE","TERMINAL","TERMINATE","TEST","TEXT","THAN","THEN",
>
> "THROUGH","THRU","TIME","TIMES","TO","TOP","TRAILING","TRUE","TYPE",
>
> "UNIT","UNSTRING","UNTIL","UP","UPON","USAGE","USE","USING","VALUE",
>
> "VALUES","VARYING","WHEN","WITH","WORDS","WORKING-STORAGE","WRITE",
>
> "ZERO","ZEROES","ZEROS","+","-","*","/","**",">","<","=",">=","<="};
>
>         // Constuctor for no parameter
>         public CodeStatistics(String csServerName)
>         {
>             openSqlConnection(csServerName);
>         }
>
>         // Constructor for passed Element ID
>         public CodeStatistics(String csServerName, String csElementId)
>         {
>             openSqlConnection(csServerName);
>             retrieveElementInfo(csElementId);
>         }
>
>         // Establish the element for this class instance
>         public void retrieveElementInfo(String reiElementId)
>         {
>             // Retrieve the information about the passed program
>             SqlCommand cmd = new SqlCommand("SELECT element_id,
> element_type, element_subtype, server_name "
>                 + "FROM active_elements "
>                 + "WHERE element_id = '" + reiElementId.Trim() + "'",
> dbConn);
>             SqlDataReader dr = cmd.ExecuteReader();
>             if (dr.Read())
>             {
>                 elementType    =
> Convert.ToChar(dr["element_type"].ToString().Trim().Substring(0,1));
>                 elementSubType = dr["element_subtype"].ToString().Trim();
>                 fileName       = dr["server_name"].ToString().Trim();
>                 elementId      = reiElementId;
>             }
>             dr.Close();
>             dr.Dispose();
>         }
>
>         // Update the statistics for the element ID
>         public void updateStatistics(String usPath, String usProcessName)
>         {
>             if (File.Exists(usPath + fileName))
>             {
>                 String textLine = "";
>
>                 // Depending on the type, clear out the cross-reference
> tables
>                 switch (elementType)
>                 {
>                     case 'P':
>                     case 'L':
>                         SqlCommand scDel = new SqlCommand();
>                         scDel.Connection = dbConn;
>
>                         // Delete item/proc xref
>                         scDel.CommandText = "DELETE FROM Proc_Prog_Xref
> WHERE ProgName = '" + elementId + "'";
>                         scDel.ExecuteNonQuery();
>
>                         // Delete item/reject xref
>                         scDel.CommandText = "DELETE FROM RejectsXref WHERE
> program = '" + elementId + "'";
>                         scDel.ExecuteNonQuery();
>
>                         // Delete item/call xref
>                         scDel.CommandText = "DELETE FROM
> sdp_CSCI_Call_Xref WHERE Element_ID = '" + elementId + "'";
>                         scDel.ExecuteNonQuery();
>
>                         // Delete cull information
>                         scDel.CommandText = "DELETE FROM sdp_Dbe_Csci_Xref
> WHERE CSCI = '" + elementId + "'";
>                         scDel.ExecuteNonQuery();
>                         scDel.CommandText = "DELETE FROM sdp_Dbr_Csci_Xref
> WHERE CSCI = '" + elementId + "'";
>                         scDel.ExecuteNonQuery();
>
>                         scDel.Dispose();
>                         break;
>                 }
>
>                 StreamReader file = File.OpenText(usPath + fileName);
>
>                 while (!file.EndOfStream)
>                 {
>                     textLine = file.ReadLine().ToUpper();
>
>                     if ((elementType != 'P') && (elementType != 'L'))
>                     {
>                         textLine = textLine.Trim();
>                     }
>
>                     countLine(textLine); // Count this line as a "line of
> code"
>
>                     switch(elementType)
>                     {
>                         case 'P':
>                         case 'L':
>                             textLine = textLine.Replace(",", "
> ").Replace(".", " ").Trim();
>                             updateProcXref(textLine);
>                             updateRejectXref(textLine, usProcessName);
>                             updateCallXref(textLine);
>                             //updateCull(textLine);
>                             break;
>                     }
>
>                 }
>
>                 file.Close();
>                 file.Dispose();
>
>                 if (programID.Count > 0)
>                 {   // Delete any references to calls if the target is
> defined in the program (i.e., nested subprograms)
>                     SqlCommand scDelete = new SqlCommand();
>
>                     scDelete.CommandText = "DELETE FROM sdp_CSCI_CALL_Xref
> "
>                         + "WHERE Element_ID = '" + elementId + "' "
>                             + "AND Call_Name IN ('";
>                     for (int i = 0; i < programID.Count; i++)
>                     {
>                         scDelete.CommandText += programID[i] + "'";
>                         if (i < (programID.Count - 1))
>                         {
>                             scDelete.CommandText += ",'";
>                         }
>                     }
>                     scDelete.CommandText += ")";
>                     scDelete.Connection = dbConn;
>                     scDelete.ExecuteNonQuery();
>                     scDelete.Dispose();
>                 }
>
>                 // Update LOC in the CSCS database
>                 SqlCommand sc = new SqlCommand("UPDATE Active_Elements "
>                     + "SET   Commented_Lines  = " +
> locCommented.ToString()
>                         + ", Executable_Lines = " +
> locExecutable.ToString()
>                         + ", Total_Lines      = " + locTotal.ToString()
>                     + "WHERE Element_ID = '" + elementId + "'", dbConn);
>                 sc.ExecuteNonQuery();
>                 sc.Dispose();
>             }
>         }
>
>         protected void countLine(String clLine)
>         {
>             String commentStart  = "";
>             String commentEnd    = "";
>             String commentSingle = "";
>
>             // A line is a line...
>             locTotal++;
>
>             if (clLine != "")
>             {
>                 switch(elementType)
>                 {
>                     case 'P':
>                     case 'L':
>                         // COBOL
>                         if ((clLine.Length > 6) && (clLine.Substring(6,1)
> == "*"))
>                         {
>                             locCommented++;
>                         }
>                         else
>                         {
>                             locExecutable++;
>                         }
>                         break;
>
>                     case 'G':
>                         // GUI
>                         if ((elementSubType == "HTML") || (elementSubType
> == "CSS") || (elementSubType == "XML"))
>                         {
>                             commentStart = "<!--";
>                             commentEnd   = "-->";
>                         }
>                         else
>                         {
>                             if (elementSubType == "XSLT")
>                             {
>                                 commentStart = "<xsl:comment>";
>                                 commentEnd   = "</xsl:comment>";
>                             }
>                             else
>                             {
>                                 if (elementSubType == "JS")
>                                 {
>                                     commentStart  = "/*";
>                                     commentEnd    = "*/";
>                                     commentSingle = "//";
>                                 }
>                             }
>                         }
>
>                         if ((commentStart == "") && (commentEnd == "") &&
> (commentSingle == ""))
>                         {   // We don't look for comments - if it's not
> blank, it's executable
>                             locExecutable++;
>                         }
>                         else
>                         {
>                             if (inComment)
>                             {   // We're in a multi-line comment
>                                 locCommented++;
>                                 if (clLine.IndexOf(commentEnd) >= 0)
>                                 {   // This is the last line of the
> multi-line comment
>                                     inComment = false;
>                                 }
>                             }
>                             else
>                             {
>                                 if (clLine.IndexOf(commentStart) >= 0)
>                                 {
>                                     if (clLine.IndexOf(commentEnd) == -1)
>                                     {   // Start of a multi-line comment
>                                         inComment = true;
>                                     }
>                                     if ((clLine.IndexOf(commentStart) ==
> 0))
>                                     {   // Nothing before the comment -
> the entire line is commented
>                                         locCommented++;
>                                     }
>                                     else
>                                     {   // Something before the comment -
> count the line as executable
>                                         locExecutable++;
>                                     }
>                                 }
>                                 else
>                                 {
>                                     if ((commentSingle != "") &&
> (clLine.IndexOf(commentSingle) >= 0))
>                                     {
>                                         if (clLine.IndexOf(commentSingle)
> == 0)
>                                         {   // The entire line is a
> comment
>                                             locCommented++;
>                                         }
>                                         else
>                                         {   // Only the end of the line is
> commented
>                                             locExecutable++;
>                                         }
>                                     }
>                                     else
>                                     {
>                                         locExecutable++;
>                                     }
>                                 }
>                             }
>                         }
>                         break;
>
>                     case 'R':
>                         // Runstreams
>                         if ((elementSubType == "IPF") &&
> (clLine.Substring(0,1) == "@"))
>                         {   // IPF comment character
>                             locCommented++;
>                         }
>                         else
>                         {
>                             if ((elementSubType == "QLP") &&
> (clLine.Substring(0,1) == "*"))
>                             {   // QLP comment character
>                                 locCommented++;
>                             }
>                             else
>                             {   // Apply ECL comment rules
>                                 if ((clLine.Length > 2) &&
> ((clLine.Substring(0,3) == "@ .") || (clLine.Substring(0,3) == "@. ")))
>                                 {   // ECL comment character
>                                     locCommented++;
>                                 }
>                                 else
>                                 {
>                                     locExecutable++;
>                                 }
>                             }
>                         }
>                         break;
>
>                     case 'Q':
>                         // IQ/U Runstreams
>                         if (clLine.Substring(0,1) == ".")
>                         {
>                             locCommented++;
>                         }
>                         else
>                         {
>                             locExecutable++;
>                         }
>                         break;
>
>                     default:
>                         // Anything else, a non-blank line is executable
>                         locExecutable++;
>                         break;
>                 }
>             }
>         }
>
>         protected void updateProcXref(String upxLine)
>         {
>             // For this to work right, we need all items separated by only
> one space
>             upxLine = normalizeSpace(upxLine);
>
>             switch (elementType)
>             {
>                 case 'P':
>                     // Establish the cross-reference based on copy
> statement
>                     if ((upxLine.Length > 6) && (upxLine.Substring(0,5) ==
> "COPY "))
>                     {
>                         String[] words  = upxLine.Split(' ');
>                         String[] pieces = words[1].Split('-');
>
>                         if (isElement(pieces[0]))
>                         {   // See if this is already in the
> cross-reference
>                             SqlCommand scCheck = new SqlCommand("SELECT
> ProgName FROM Proc_Prog_Xref "
>                                 + "WHERE   ProgName   = '" + elementId +
> "' "
>                                     + "AND ProcName   = '" + pieces[0] +
> "' "
>                                     + "AND EntryPoint = '" + words[1] +
> "'", dbConn);
>                             SqlDataReader drCheck =
> scCheck.ExecuteReader();
>                             if (!drCheck.HasRows)
>                             {   // Add this program/proc to the table
>                                 executeSQL("INSERT INTO Proc_Prog_Xref "
>                                     + "(ProgName, ProcName, Passive,
> EntryPoint) "
>                                     + "VALUES ('" + elementId + "','" +
> pieces[0] + "',0,'" + words[1] + "')");
>                             }
>                             drCheck.Close();
>                             drCheck.Dispose();
>                             scCheck.Dispose();
>                         }
>                     }
>                     break;
>
>                 case 'L':
>                     // Establish the cross-reference based on perform
> statement
>                     if ((upxLine.Length > 9) && (upxLine.Substring(0,8) ==
> "PERFORM "))
>                     {
>                         String[] words  = upxLine.Split(' ');
>                         String[] pieces = words[1].Split('-');
>
>                         // Don't count performs of the proc itself
>                         if ((pieces[0] != elementId) &&
> (isElement(pieces[0])))
>                         {   // See if this is already in the xref
>                             SqlCommand scCheck = new SqlCommand("SELECT
> ProgName FROM Proc_Prog_Xref "
>                                 + "WHERE ProgName = '" + elementId + "' "
>                                     + "AND ProcName = '" + pieces[0] +
> "'", dbConn);
>                             SqlDataReader drCheck =
> scCheck.ExecuteReader();
>                             if (!drCheck.HasRows)
>                             {
>                                 executeSQL("INSERT INTO Proc_Prog_Xref "
>                                     + "(ProgName, ProcName, Passive,
> EntryPoint) "
>                                     + "VALUES ('" + elementId + "','" +
> pieces[0] + "',1,NULL)");
>                             }
>                             drCheck.Close();
>                             drCheck.Dispose();
>                             scCheck.Dispose();
>                         }
>                     }
>                     break;
>             }
>         }
>
>         protected void updateRejectXref(String urxLine, String
> urxProcessName)
>         {
>             Int32 rejectCode;
>
>             // Get rid of extra spaces
>             urxLine = normalizeSpace(urxLine);
>
>             if ((urxLine.IndexOf("REJCDE") >= 0) && (urxLine.IndexOf("MOVE
> ") >= 0))
>             {   // Line is "MOVE [something] TO REJCDE"
>                 String[] words = urxLine.Split(' ');
>                 if (Int32.TryParse(words[1], out rejectCode))
>                 {
>                     // Mask off narratives to get the lowest 4 digits
>                     rejectCode = rejectCode % 10000;
>
>                     if (rejectCode > 0)
>                     {   // Is this reject already in the xref?
>                         SqlCommand scCheck = new SqlCommand("SELECT
> program FROM RejectsXref "
>                             + "WHERE program = '" + elementId + "' "
>                                 + "AND reject_num = " +
> rejectCode.ToString(), dbConn);
>                         SqlDataReader drCheck = scCheck.ExecuteReader();
>                         if (!drCheck.HasRows)
>                         {   // Insert it
>                             executeSQL("INSERT INTO RejectsXref "
>                                 + "(program, reject_num, last_updated,
> last_updated_by) "
>                                 + "VALUES ('" + elementId + "'," +
> rejectCode.ToString()
>                                 + ",current_timestamp,'" + urxProcessName
> + "')");
>                         }
>                         drCheck.Close();
>                         drCheck.Dispose();
>                         scCheck.Dispose();
>                     }
>                 }
>             }
>         }
>
>         protected void updateCallXref(String ucxLine)
>         {
>             String[] words = normalizeSpace(ucxLine).Split(' ');
>
>             // Check for "PROGRAM-ID"
>             if (words[0] == "PROGRAM-ID")
>             {   // Save these off - we'll delete them at the end
>                 programID.Add(words[1]);
>             }
>
>             if ((words.Length > 1) && (words[0] == "CALL"))
>             {
>                 if ((words[1].Substring(0,1) == "\"") ||
> (words[1].Substring(0,1) == "'"))
>                 {   // Calling a literal - this is one we'll store
>                     String callName =
> words[1].Substring(1,words[1].Length - 2);
>
>                     SqlCommand scCheck = new SqlCommand("SELECT Element_ID
> FROM sdp_CSCI_CALL_Xref "
>                         + "WHERE Element_ID = '" + elementId + "' "
>                             + "AND Call_Name = '" + callName + "'",
> dbConn);
>                     SqlDataReader drCheck = scCheck.ExecuteReader();
>                     if (!drCheck.HasRows)
>                     {   // It's not there - insert it
>                         executeSQL("INSERT INTO sdp_CSCI_CALL_Xref "
>                             + "(Element_ID, Call_Name) "
>                             + "VALUES ('" + elementId + "','" + callName +
> "')");
>                     }
>                     drCheck.Close();
>                     drCheck.Dispose();
>                     scCheck.Dispose();
>                 }
>             }
>         }
>
>         protected void updateCull(String ucLine)
>         {
>             ucLine = normalizeSpace(ucLine);
>
>             if (   (ucLine.IndexOf("FETCH ")  >= 0) ||
> (ucLine.IndexOf("FIND ")   >= 0)
>                 || (ucLine.IndexOf("MODIFY ") >= 0) ||
> (ucLine.IndexOf("STORE ")  >= 0)
>                 || (ucLine.IndexOf("DELETE ") >= 0) ||
> (ucLine.IndexOf("INSERT ") >= 0)
>                 || (ucLine.IndexOf("REMOVE ") >= 0))
>             {
>                 updateCullRecord(ucLine);
>             }
>             else
>             {
>                 // Split up the words, and check for a DMS field name or
> R-proc data name
>                 String[] words = ucLine.Split(' ');
>                 for (int i = 0; i < words.Length; i++)
>                 {
>                     if ((!isCobolKeyword(words[i])) &&
> (!hasSymbols(words[i])))
>                     {
>                         updateCullItem(words[i], ucLine);
>                     }
>                 }
>             }
>         }
>
>         // Update DML records in cull
>         protected void updateCullRecord(String ucrLine)
>         {
>             String[] words  = ucrLine.Split(' ');
>             Int32    word   = 0;
>             String   column = "";
>
>             // --- CHECK #1 --- record name //
>
>             // Find the word where we're doing the DML
>             while ((words[word] != "FETCH")  && (words[word] != "FIND")
>                 && (words[word] != "MODIFY") && (words[word] != "STORE")
>                 && (words[word] != "DELETE") && (words[word] != "INSERT")
>                 && (words[word] != "REMOVE") && (word < words.Length))
>             {
>                 word++;
>             }
>
>             if ((word < (words.Length - 2))
>                 && ((   words[word + 1] == "FIRST") || (words[word + 1] ==
> "NEXT")
>                     || (words[word + 1] == "PRIOR") || (words[word + 1] ==
> "LAST")))
>             {   // "FETCH FIRST xxx", etc.
>                 word++;
>             }
>
>             if ((word < (words.Length - 2)) && (words[word + 1] !=
> "RECORD"))
>             {
>                 // Determine the proper column name
>                 if ((words[word] == "FETCH") || (words[word] == "FIND"))
>                 {
>                     column = "Fetches";
>                 }
>                 else
>                 {
>                     if (words[word] == "MODIFY")
>                     {
>                         column = "Modifies";
>                     }
>                     else
>                     {
>                         column = words[word].ToLower() + "s";
>                     }
>                 }
>
>                 // The next word may be a record name
>                 String recordName = words[++word];
>
>                 // Is this name a valid record?
>                 SqlCommand scRecChk = new SqlCommand("SELECT record_name
> FROM dms_records "
>                     + "WHERE record_name = '" + recordName + "'", dbHelp);
>                 SqlDataReader drRecChk = scRecChk.ExecuteReader();
>
>                 if (drRecChk.HasRows)
>                 {   // Does the record already exist in the
> cross-reference?
>                     SqlCommand scCheck = new SqlCommand("SELECT CSCI FROM
> sdp_Dbr_Csci_Xref "
>                         + "WHERE Dbr = '" + recordName + "' "
>                             + "AND Csci = '" + elementId + "'", dbConn);
>                     SqlDataReader drCheck = scCheck.ExecuteReader();
>
>                     if (!drCheck.HasRows)
>                     {   // Add a new zeroed-out row
>                         SqlCommand scInsert = new SqlCommand("INSERT INTO
> sdp_Dbr_Csci_Xref "
>                             + "(Dbr, Csci, Fetches, Modifies, Inserts,
> Stores, Removes, Deletes) "
>                             + "VALUES ('" + recordName + "','" + elementId
> + "',0,0,0,0,0,0)", dbConn);
>                         scInsert.ExecuteNonQuery();
>                         scInsert.Dispose();
>                     }
>
>                     drCheck.Close();
>                     drCheck.Dispose();
>                     scCheck.Dispose();
>
>                     // Update this count
>                     SqlCommand scUpdate = new SqlCommand("UPDATE
> sdp_Dbr_Csci_Xref "
>                         + "SET " + column + " = " + column + " + 1 "
>                         + "WHERE Dbr = '" + recordName + "' "
>                             + "AND Csci = '" + elementId + "'", dbConn);
>                     scUpdate.ExecuteNonQuery();
>                     scUpdate.Dispose();
>                 }
>
>                 drRecChk.Close();
>                 drRecChk.Dispose();
>                 scRecChk.Dispose();
>             }
>
>             // --- CHECK #2 --- set name //
>
>             if ((ucrLine.IndexOf(" SET") >= 0) || (ucrLine.IndexOf("VIA ")
 
>             {
>                 String setName = "";
>
>                 // Find the word "via" or "set"
>                 word = 0;
>                 while ((words[word] != "VIA") && (words[word] != "SET"))
>                 {
>                     word++;
>                 }
>
>                 if ((words[word] == "SET") && (word > 0))
>                 {   // "FETCH xxx WITHIN xxxx SET", "REMOVE xxxx FROM
> xxxxx SET", etc.
>                     setName = words[--word];
>                 }
>                 else
>                 {
>                     if ((words[word] == "VIA") && (word <
> (words.Length -1)))
>                     {   // "FETCH xxx VIA xxxx USING xxxx" format
> statement
>                         setName = words[++word];
>                     }
>                 }
>
>                 if (setName != "")
>                 {
>                     // Is this a valid set name?
>                     SqlCommand scSetChk = new SqlCommand("SELECT set_name
> FROM dms_sets "
>                         + "WHERE set_name = '" + setName + "'", dbHelp);
>                     SqlDataReader drSetChk = scSetChk.ExecuteReader();
>
>                     if (drSetChk.HasRows)
>                     {
>                         // What column name do we update?
>                         column = "";
>
>                         if ((ucrLine.IndexOf("FETCH ") >= 0) ||
> (ucrLine.IndexOf("FIND ") >= 0))
>                         {   column = "Fetches";
>                         }
>                         else
>                         {   if (ucrLine.IndexOf("INSERT") >= 0)
>                             {   column = "Inserts";
>                             }
>                             else
>                             {   if (ucrLine.IndexOf("REMOVE") >= 0)
>                                 {   column = "Removes";
>                                 }
>                             }
>                         }
>
>                         if (column != "")
>                         {   // Does it already exist in the
> cross-reference?
>                             SqlCommand scCheck = new SqlCommand("SELECT
> Dbr FROM sdp_Dbr_Csci_Xref "
>                                 + "WHERE Dbr = '" + setName + "'",
> dbConn);
>                             SqlDataReader drCheck =
> scCheck.ExecuteReader();
>
>                             if (!drCheck.HasRows)
>                             {   // Insert a new blank row
>                                 SqlCommand scInsert = new
> SqlCommand("INSERT INTO sdp_Dbr_Csci_Xref "
>                                     + "(Dbr, Csci, Fetches, Modifies,
> Inserts, Stores, Removes, Deletes) "
>                                     + "VALUES ('" + setName + "','" +
> elementId + "',0,0,0,0,0,0)", dbConn);
>                                 scInsert.ExecuteNonQuery();
>                                 scInsert.Dispose();
>                             }
>
>                             drCheck.Close();
>                             drCheck.Dispose();
>                             scCheck.Dispose();
>
>                             SqlCommand scUpdate = new SqlCommand("UPDATE
> sdp_Dbr_Csci_Xref "
>                                 + "SET " + column + " = " + column + " + 1
> "
>                                 + "WHERE Dbr = '" + setName + "' "
>                                     + "AND Csci = '" + elementId + "'",
> dbConn);
>                             scUpdate.ExecuteNonQuery();
>                             scUpdate.Dispose();
>                         }
>                     }
>
>                     drSetChk.Close();
>                     drSetChk.Dispose();
>                     scSetChk.Dispose();
>                 }
>             }
>         }
>
>         protected void updateCullItem(String uciWord, String uciLine)
>         {
>             bool used    = false;
>             bool updated = false;
>
>             // Check to see if the word starts with "R" and has a dash,
> and is not this proc
>             if ((uciWord.Substring(0,1) == "R") && (uciWord.Substring(3,1)
> == "-")
>                 && (uciWord.Substring(0,4) != elementId))
>             {
>                 if (uciLine.IndexOf("PERFORM") >= 0)
>                 {   // We've got a paragraph name performed
>                     SqlCommand scTables = new SqlCommand("SELECT DISTINCT
> table_name rt "
>                         + "FROM rdms_tables rt, rdms_table_columns rtc "
>                         + "WHERE rt.table_name = rtc.table_name "
>                             + "AND rtc.r_proc_element_name LIKE '" +
> uciWord.Substring(0,4) + "%'",dbHelp);
>                     SqlDataReader drTables = scTables.ExecuteReader();
>
>                     while(drTables.HasRows)
>                     {   // See if this table already exists in the cull
> look-up
>                         int i = 0; // !WORK this is crap
>                     }
>                 }
>                 else
>                 {
>                     if (uciLine.IndexOf("MOVE") >= 0)
>                     {
>                         if (uciLine.IndexOf("TO") >
> uciLine.IndexOf(uciWord))
>                         {
>                             used = true;
>                         }
>                         else
>                         {
>                             updated = true;
>                         }
>                     }
>                     else
>                     {
>                         updated = true;
>                     }
>                 }
>             }
>             else
>             {   // See if the word is a valid DMS field
>             }
>         }
>
>         // Establish connections with the database
>         protected void openSqlConnection(String oscServerName)
>         {
>             String connString = "";
>
>             if (oscServerName == "") {
>                 oscServerName = "[servername]";
>             }
>
>             connString = "server=" + oscServerName +
> ";database=[database];User ID=[user];Password=[password];";
>             dbConn = new SqlConnection(connString);
>             dbConn.Open();
>
>             connString =
> connString.Replace("[database],"[another-database]");
>             dbHelp = new SqlConnection(connString);
>             dbHelp.Open();
>         }
>
>         public String cscsRegValue(String crvKey)
>         {
>             SqlCommand crvCmd = new SqlCommand("SELECT reg_value "
>                 + "FROM sdp_registry "
>                 + "WHERE reg_key = '" + crvKey + "'", dbConn);
>             SqlDataReader crvDR = crvCmd.ExecuteReader();
>             if (crvDR.Read())
>             {
>                 return(crvDR["reg_value"].ToString().Trim());
>             }
>             else
>             {
>                 return("");
>             }
>         }
>
>         protected void executeSQL(String esText)
>         {
>             SqlConnection esConn = new
> SqlConnection(dbConn.ConnectionString + "password=[password];");
>             SqlCommand    esCmd  = new SqlCommand(esText, esConn);
>             esConn.Open();
>             esCmd.ExecuteNonQuery();
>             esCmd.Dispose();
>             esConn.Close();
>             esConn.Dispose();
>         }
>
>         // Eliminates all embedded spaces more than one
>         protected String normalizeSpace(String nsText)
>         {
>             String workText = nsText;
>
>             while (workText.IndexOf("  ") >= 0)
>             {
>                 workText = workText.Replace("  "," ");
>             }
>             return(workText);
>         }
>
>         // Returns "true" if the text passed is an element in CSCS
>         protected bool isElement(String ieText)
>         {
>             Boolean itExists = false;
>
>             SqlCommand ieCmd = new SqlCommand("SELECT Actv_Ind FROM
> Active_Elements "
>                 + " WHERE Element_ID = '" + ieText + "'", dbConn);
>             SqlDataReader ieDR  = ieCmd.ExecuteReader();
>             if (ieDR.HasRows) {
>                 itExists = true;
>             }
>             ieDR.Close();
>             ieDR.Dispose();
>             ieCmd.Dispose();
>
>             return(itExists);
>         }
>
>         // Returns "true" if the word passed is a COBOL keyword
>         protected bool isCobolKeyword(String ickText)
>         {
>             Int32 i = 0;
>             while ((i < cobolKeywords.Length) && (ickText !=
> cobolKeywords[i]))
>             {
>                 i++;
>             }
>             if (i < cobolKeywords.Length)
>             {
>                 return(true);
>             }
>             else
>             {
>                 return(false);
>             }
>         }
>
>         // Returns "true" if the words passed has symbols in it
>         protected bool hasSymbols(String hsText)
>         {
>             if (   (hsText.IndexOf("(")  >= 0) || (hsText.IndexOf(")") 
>                 || (hsText.IndexOf("\"") >= 0) || (hsText.IndexOf("'") 
>                 || (hsText.IndexOf("_")  >= 0))
>             {
>                 return(true);
>             }
>             else
>             {
>                 return(false);
>             }
>         }
>
>     }
> }
>
> --
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
> ~   /   \  /         ~        Live from Montgomery, AL!       ~
> ~  /     \/       o  ~                                        ~
> ~ /      /\   -   |  ~          daniel@thebelowdomain         ~
> ~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
> ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
> ~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
> ~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
> ~ h---- r+++ z++++                                            ~
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
>
> "Who is more irrational?  A man who believes in a God he doesn't see, or a
> man who's offended by a God he doesn't believe in?" - Brad Stine[/color]



Report this thread to moderator Post Follow-up to this message
Old Post
Pete Dashwood
02-01-07 02:55 AM


Re: [OT] My First C# (warning - long post)
Pete Dashwood wrote:
> Hi Daniel,
>
> Unfortunately, much as I'd like to, I'm just too busy at the moment to
> analyse this properly.
>
> Fortunately, Andrew is doing so (I had a quick look at his comments and
> endorse them 100%) and one set of criticisms is probably all you need on a
> first attempt :-)

I'm a big guy (well, metaphorically).  I can take it.

> I formed some first impressions from a quick look (before I saw Andrew's
> comments.... :-)) and they were as follows:
>
> 1. It is a procedural translation into an OO environment. Even down to the
> "Working-storage" at the top of the Class... :-)

Aw man, cut me some slack - show me a COBOL program with less than 15
working-storage variables!  :)  (The reason I did this that way,
especially for the block of private ones, was just so that the memory
didn't have to be loaded every time.  Can you imagine loading that array
of COBOL keywords every time isCobolKeyword is called?)

> 2. You show an excellent grasp of using functions and, at the nitty-gritty
> level you have it sussed. (I think you may be over-using Trim()...
> "Convert.ToChar(dr["element_type"].ToString().Trim().Substring(0,1))" seem
s
> a bit unnecessary to me, when all you are wanting is one byte, but I haven
't
> checked the details...:-)

You'd think that you could cast a substring of one character TO a
character, wouldn't you?  Yes, the Trim() is probably extra now, but
that was my attempt to get it to quit griping at me that I had given it
a "String", when it wanted a "char".  (I know in Java you can't do a
switch on a string - I'm guessing that it's that way in C# as well.  If
not, then I spent 20 minutes wasting my time...  :>  Which wouldn't
surprise me to find out...)

> 3. The embedded SQL is just a hangover from procedural code; it is
> inefficient and ugly.  Think in tiers; separate data access from business
> logic. Treat db connections as precious; don't hold them any longer than y
ou
> need to. I posted a link previously which outlines the C# approach and it 
is
> quite different from the procedural embedded SQL approach. (Since my own
> stuff is now working, I can also confirm that it is VERY fast...)

See my post to Andrew on this topic - how?

> 4.  I think you are very lucky to have someone like Andrew looking at it. 
I
> read his comments and agree almost entirely. (I think 10 lines is  a bit t
oo
> rigid a rule, but the principle is correct.). In OO, as in most online
> processing, "small is beautiful"... Andrew's point about refactoring is an
> excellent one and I wouldn't have thought of that as a good way to improve
> what you have; I've learned from this interchange :-)

I really appreciate him doing it.

I realized today how much of a g I am.  I have Visual C# 2005 Express
Edition, Eclipse (for Java 2 1.5), Fujitsu COBOL, and Visual SlickEdit
all on one machine.  Wow...

> 5. You deserve credit for posting ANY code here, and to post a first
> attempt, is brave and  admirable. I know you won't take the comments to
> heart in a negative way.

I won't.  Of course, that's also why I posted my list of caveats before
the code - there are things about it I don't like, but when the IDE or
shop standards enforce "style", it's hard to take any complaints about
it personally.

> 6. You might think about offloading a lot of the literals into external
> data. C# provides a number of places where you can put stuff... System
> collections, XML files, configuration data, to name a few. The COBOL
> Reserved Word list could be an XML file that gets loaded once at startup,
> rather than being embedded in the program.

I was thinking that there *had* to be a better way to do that.  Can you
make a static XML that gets "built into" (whatever the C# term for that
would be) the .dll file?

> For my money, you need to start thinking in terms of a production line.
> Think about a series of (small) machines (components) that take scrap meta
l
> in one end and push knives and forks out the other. Each machine carries o
ut
> another step in the process, each machine does exactly what it does, and
> functionality does not overlap. (Think encapsulation and "black boxes").
> Some machines provide support functions to machines on the main line, but
> for each machine, the goals it must achieve are clear, and the primary foc
us
> for it, from which it must not be distracted by having to do ancilliary an
d
> support functions (like accessing databases). Think of machines in each
> layer (tier) of the production process. (A component needs to validate,
> retrieve, or update certain data? It should focus on what it is going to D
O
> with that data and leave the "lower order" functions to other components w
ho
> deal with that. It can simply activate a "retriever" and know that what
> comes back is valid and timely or whatever...) Activate the retriever; tak
e
> what it returns, get on with what this component is really about...:-)

I'd really love to do this...  Gotta get the grey matter aligned properly...

> Still, you have demonstrated a really good grasp of the language itself, t
he
> program works, and it can be made more elegant fairly easily. All in all,
> pretty good for a first attempt :-)

Thanks.  It really is a piece of cake - I've converted three ASPs to
ASP.NET/C# pages in 2 days (6 if you count the little ones I'm working
on now).  It took me a little over a day on the first one, then it just
clicked.  Of course, it's probably still procedural C#, but it's fast.  :)

This DB abstraction layer would be good for our system as a whole.  The
entire thing will be ASP.NET/C# when we're (er, I guess that should be
"they're") done.  I'm guessing that, once I get that built, we would
just give it a namespace (maybe CSCS.DataUtilities or something like
that), then import, er, "using" it in our classes/pages?

--
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
~   /   \  /         ~        Live from Montgomery, AL!       ~
~  /     \/       o  ~                                        ~
~ /      /\   -   |  ~          daniel@thebelowdomain         ~
~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
~ h---- r+++ z++++                                            ~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~

"Who is more irrational?  A man who believes in a God he doesn't see, or
a man who's offended by a God he doesn't believe in?" - Brad Stine

Report this thread to moderator Post Follow-up to this message
Old Post
LX-i
02-01-07 08:55 AM


Re: [OT] My First C# (warning - long post)
"LX-i" <lxi0007@netscape.net> wrote in message
 news:d8eb1$45c17062$454920f8$31633@KNOLO
GY.NET...
> Pete Dashwood wrote: 
>
> I'm a big guy (well, metaphorically).  I can take it.
> 
>
> Aw man, cut me some slack - show me a COBOL program with less than 15
> working-storage variables!  :)

I did cut you some slack... Have a look at properties if you really want
global variables
(The reason I did this that way,
> especially for the block of private ones, was just so that the memory
> didn't have to be loaded every time.  Can you imagine loading that array
> of COBOL keywords every time isCobolKeyword is called?)
>
No, and I wouldn't do it... :-)
 
>
> You'd think that you could cast a substring of one character TO a
> character, wouldn't you?  Yes, the Trim() is probably extra now, but that
> was my attempt to get it to quit griping at me that I had given it a
> "String", when it wanted a "char".  (I know in Java you can't do a switch
> on a string - I'm guessing that it's that way in C# as well.  If not, then
> I spent 20 minutes wasting my time...  :>  Which wouldn't surprise me to
> find out...)

Don't make Java assumptions about C#. You can certainly switch on a char or
string, (as long as they are constant). When it "gripes" at you, there is a
reason. I consider these gripes as a voice saying: "Pete, you are about to
learn something..." :-) Fortunately, as the learning process proceeds, the
voice becomes less insistent. But you have to listen to it, do the homework,
and not just look for a way to dismiss it as an irritation... :-)

Here's a sample from live code that covers Casting string to Char, setting
up a Global property, and managing a COBOL data block in C#...

}

private  string _IBreturn;

// A read-write instance property:

public  string IBreturn

{

get

{

return _IBreturn;

}

set

{

_IBreturn = value;

_IBreturn = _IBreturn.PadRight(5, char.Parse("0"));

_IntBlock = _IBreturn +

_IntBlock.Substring

(_IBreturn.Length,_IntBlock.Length -
_IBreturn.Length);

}

}

(As you can see, I do not share your aversion to braces surrounding code
blocks being on a new line, and I actually find this helpful...)

The "set" method inserts a Pic x(5) return code into the start of an
interface block, defined  as a COBOL structure of 8192 bytes (this is for
compatibility with COM BSTRING type.)

The return code must be padded with zeroes if it does not occupy the full 5
bytes. Although _IBreturn is a string, it must be padded with Chars. You may
consider this is "cheating" so here's a direct cast to char, also taken from
live code :-)...

string temp = ", [";

char[] trimChars = temp.ToCharArray();





(There is no need for ConvertTo, SubString or Trim as any string contains
the knowledge to cast itself to a char array...)





The final action of the "set" method above is to update the COBOL interface
block with the new return code. Note that the return code is a private field
that cannot be accessed other than by means of the get and set methods; the
public copy of the field automatically uses these methods when it is
referenced. You could argue that this is unnecessary; why not just slice a
subtring of  _intBlock when you want the return code?  It is unwieldy to
keep referencing substrings of an 8K string simply to get 5 bytes. Keeping
each field in the block separate as a private property and updating the
block when they get changed, by means of their set methods, seems to work
pretty well. I can aso "audit" the integrity of the block because I have
each field of it as a separate entity. The entire block can be easily
reconstructed from these fields and that might not be so easy if it is being
sliced left right and centre. Finally, this approach lends itself to
automation and can be easily generated  from COBOL definitions.



But, most importantly of all, the code that deals with the fields in the
block can simply reference them, and the block is automatically updated if
any of the fields are changed (remember what I said about support methods
doing the lower-order tasks?) so there is no concern about "housekeeping"
when working on these fields and, because they are public properties, they
are visible to all methods of the Class.



It's kind of like "intelligent working-storage"... :-)

> 
>
> See my post to Andrew on this topic - how?



Did you even look at the article I referenced? :-) It not only explains How,
it shows WHY :-)



Setting a connection and issuing SQL is pretty unavoidable, but after that
there is a big difference between using a SQL reader and using a
DataAdapter/DataSet. The DataSet has methods and properties that are really
useful (and  :-)). You simply don't get them if you just write embedded
SQL or open a cursor. The DataAdapter allows you to process everythng and
only apply the updates at the end when you are satisfied - the DataSet
automatically notifies errors if you change something incorrectly.



Have a look at the Data facilities in VS 2005. If you know what you're going
to be accessing, it will build the code for you in minutes. My stuff is
completely dynamic and designed to work with any database of a given family,
so I need to know what the structure is at runtime. DataSet methods and
properties give me that. It was really problematic for me NOT to be able to
use the facilities in VS 2005 because of the unknown nature of what I would
be accessing. Time and again I realised that the IDE would generate the code
if I could simply tell it what I wanted. I spent many hours combing the
support and help to understand the new (to me) concepts and finally get what
I needed. I still can't believe it actually works, but it does :-)




> 
>
> I really appreciate him doing it.
>
> I realized today how much of a g I am.  I have Visual C# 2005 Express
> Edition, Eclipse (for Java 2 1.5), Fujitsu COBOL, and Visual SlickEdit all
> on one machine.  Wow...



A REAL g would be able to write Fortran in ALL of them... :-)


> 
>
> I won't.  Of course, that's also why I posted my list of caveats before
> the code - there are things about it I don't like, but when the IDE or
> shop standards enforce "style", it's hard to take any complaints about it
> personally.
> 
>
> I was thinking that there *had* to be a better way to do that.  Can you
> make a static XML that gets "built into" (whatever the C# term for that
> would be) the .dll file?
> 
>
> I'd really love to do this...  Gotta get the grey matter aligned
> properly...
>



Some of the above was intended to help in this area and to put my money
where my mouth is...:-)  I really am so busy at the moment (I'm
force-feeding new information and concepts into myself , as well as
developing, so I'm pretty tired by the end of the day), but I'd like to try
and contribute if I can.



 
>
> Thanks.  It really is a piece of cake - I've converted three ASPs to
> ASP.NET/C# pages in 2 days (6 if you count the little ones I'm working on
> now).  It took me a little over a day on the first one, then it just
> clicked.  Of course, it's probably still procedural C#, but it's fast.  :)
>



At this point, it really doesn't matter whether it is technically elegant or
REAL OO... it works. As you write more of it and consider more approaches,
you'll pick up the OO stuff.


> This DB abstraction layer would be good for our system as a whole.  The
> entire thing will be ASP.NET/C# when we're (er, I guess that should be
> "they're") done.  I'm guessing that, once I get that built, we would just
> give it a namespace (maybe CSCS.DataUtilities or something like that),
> then import, er, "using" it in our classes/pages?
>



Something like that, certainly...



Pete.




Report this thread to moderator Post Follow-up to this message
Old Post
Pete Dashwood
02-01-07 12:55 PM


Re: [OT] My First C# (warning - long post)
Pete Dashwood wrote:
> "LX-i" <lxi0007@netscape.net> wrote in message
>  news:d8eb1$45c17062$454920f8$31633@KNOLO
GY.NET... 
>
> I did cut you some slack... Have a look at properties if you really want
> global variables

I thought that's what they were...  Isn't that how you define
properties?  "public [type] [name]"?

(And, I know you were cutting me some slack - I was just being silly...)

> (The reason I did this that way, 
> No, and I wouldn't do it... :-)

Along those lines - is there a better way to search through an array
other than "for (int i = 0; i < array.length; i++)"?
 
>
> Don't make Java assumptions about C#. You can certainly switch on a char o
r
> string, (as long as they are constant). When it "gripes" at you, there is 
a
> reason. I consider these gripes as a voice saying: "Pete, you are about to
> learn something..." :-) Fortunately, as the learning process proceeds, the
> voice becomes less insistent. But you have to listen to it, do the homewor
k,
> and not just look for a way to dismiss it as an irritation... :-)

I did look at it as a learning experience.  I was just frustrated at the
time because I had a 700-line+ file of C# that wouldn't execute because
of this one little problem.

> Here's a sample from live code that covers Casting string to Char, setting
> up a Global property, and managing a COBOL data block in C#...
>
>             }
>
>             private  string _IBreturn;
>
>             // A read-write instance property:
>
>             public  string IBreturn
>
>             {
>
>                 get
>
>                 {
>
>                     return _IBreturn;
>
>                 }
>
>                 set
>
>                 {
>
>                     _IBreturn = value;
>
>                     _IBreturn = _IBreturn.PadRight(5, char.Parse("0"));
>
>                     _IntBlock = _IBreturn +
>
>                                 _IntBlock.Substring
>
>                                    (_IBreturn.Length,_IntBlock.Length -
> _IBreturn.Length);
>
>                 }
>
>             }

So you put braces after the variable declaration?  That's the first time
I've seen that structure.  :)

> (As you can see, I do not share your aversion to braces surrounding code
> blocks being on a new line, and I actually find this helpful...)

Yeah, and you code in SECTIONs too!  ;)

Of course I'm kidding - that just goes to show that different folks have
different ideas of what "readable" is.  My biggest complaint in how much
north-south real estate it takes up on my screen.  I guess if my methods
were more of a proper size, I wouldn't have to scroll to see them.
Maybe that's a corollary to the 10-line rule - if you can't see it at
one time in the editor, it's too big!

(Is it double-spaced in the IDE, or was that just what happened when you
pasted it into the newsreader?)

> The "set" method inserts a Pic x(5) return code into the start of an
> interface block, defined  as a COBOL structure of 8192 bytes (this is for
> compatibility with COM BSTRING type.)

Why did you use char.Parse("0") instead of just '0'?

> The return code must be padded with zeroes if it does not occupy the full 
5
> bytes. Although _IBreturn is a string, it must be padded with Chars. You m
ay
> consider this is "cheating" so here's a direct cast to char, also taken fr
om
> live code :-)...
>
>             string temp = ", [";
>
>             char[] trimChars = temp.ToCharArray();

No, no cheating comment from me...  :)  I wonder if

dr["element_type"].ToString().ToCharArray()[0]

would do what I was trying to do there?

> The final action of the "set" method above is to update the COBOL interfac
e
> block with the new return code. Note that the return code is a private fie
ld
> that cannot be accessed other than by means of the get and set methods; th
e
> public copy of the field automatically uses these methods when it is
> referenced. You could argue that this is unnecessary; why not just slice a
> subtring of  _intBlock when you want the return code?  It is unwieldy to
> keep referencing substrings of an 8K string simply to get 5 bytes. Keeping
> each field in the block separate as a private property and updating the
> block when they get changed, by means of their set methods, seems to work
> pretty well. I can aso "audit" the integrity of the block because I have
> each field of it as a separate entity. The entire block can be easily
> reconstructed from these fields and that might not be so easy if it is bei
ng
> sliced left right and centre. Finally, this approach lends itself to
> automation and can be easily generated from COBOL definitions.

That makes sense to me.  It's a similar concept to a few tables we have
in our database at work.  They hold "interface parameters", and since
the paramaters vary for each interface, we have it broken down for each
format.  It certainly beats reference modification...  especially when
the next guy comes along and doesn't know that the number of days to
keep transaction history for this interface is in columns 4-6...  :)
 
>
> Did you even look at the article I referenced? :-) It not only explains Ho
w,
> it shows WHY :-)

I looked at it, and I sort of understand how they did it...  I'm going
to play with some things over the next few days.  I'll post what I find,
with hopefully enough COBOL references that the other folks won't toss
me out on my head.  :)

> Setting a connection and issuing SQL is pretty unavoidable, but after that
> there is a big difference between using a SQL reader and using a
> DataAdapter/DataSet. The DataSet has methods and properties that are reall
y
> useful (and  :-)). You simply don't get them if you just write embedde
d
> SQL or open a cursor. The DataAdapter allows you to process everythng and
> only apply the updates at the end when you are satisfied - the DataSet
> automatically notifies errors if you change something incorrectly.
>
> Have a look at the Data facilities in VS 2005. If you know what you're goi
ng
> to be accessing, it will build the code for you in minutes. My stuff is
> completely dynamic and designed to work with any database of a given famil
y,
> so I need to know what the structure is at runtime. DataSet methods and
> properties give me that. It was really problematic for me NOT to be able t
o
> use the facilities in VS 2005 because of the unknown nature of what I woul
d
> be accessing. Time and again I realised that the IDE would generate the co
de
> if I could simply tell it what I wanted. I spent many hours combing the
> support and help to understand the new (to me) concepts and finally get wh
at
> I needed. I still can't believe it actually works, but it does :-)

In looking at things back and forth in writing this reply, it's starting
to click.
 
>
>  A REAL g would be able to write Fortran in ALL of them... :-)

OK - I guess I'm safe...  ;)
 
>
> Some of the above was intended to help in this area and to put my money
> where my mouth is...:-)  I really am so busy at the moment (I'm
> force-feeding new information and concepts into myself , as well as
> developing, so I'm pretty tired by the end of the day), but I'd like to tr
y
> and contribute if I can.

I appreciate it.  Don't stay up late on my account.  :)
 
>
> Something like that, certainly...

Cool...  :)

--
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
~   /   \  /         ~        Live from Montgomery, AL!       ~
~  /     \/       o  ~                                        ~
~ /      /\   -   |  ~          daniel@thebelowdomain         ~
~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
~ h---- r+++ z++++                                            ~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~

"Who is more irrational?  A man who believes in a God he doesn't see, or
a man who's offended by a God he doesn't believe in?" - Brad Stine

Report this thread to moderator Post Follow-up to this message
Old Post
LX-i
02-01-07 11:55 PM


Re: [OT] My First C# (warning - long post)
LX-i<lxi0007@netscape.net> 02/01/07 7:51 AM >>>
>
>Along those lines - is there a better way to search through an array
>other than "for (int i = 0; i < array.length; i++)"?

I'm not sure specifically what you are referring to, but, if we assume the
above code is something like
string array[] = new string[10];
for (int i = 0; i < array.length; i++)
{
doSomething(array[i]);
}

You can replace it with

foreach (string s in array)
{
doSomething(s);
}

Is that what you're looking for?

http://www.c-sharpcorner.com/Upload...ays111420050603
54AM/WorkingWithArrays.aspx

MF Net Express 5.0 has something similar for COBOL, which I'll post from
home.

Frank

---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO  USA

Report this thread to moderator Post Follow-up to this message
Old Post
Frank Swarbrick
02-01-07 11:55 PM


Re: [OT] My First C# (warning - long post)
"LX-i" <lxi0007@netscape.net> wrote in message
 news:19a17$45c1fe8b$454920f8$23261@KNOLO
GY.NET...
> Pete Dashwood wrote: 
>
> I thought that's what they were...  Isn't that how you define properties?
> "public [type] [name]"?

No. Those are global variables. Click on Help in VS2005 and then click
"index". Enter "properties"... Or start with this direct local link:

ms-help://MS.VSExpressCC.v80/MS.NETFramework.v20.en/dv_csref/html/f7f67b05-0
983-4cdb-96af-1855d24c967c.htm

>
> (And, I know you were cutting me some slack - I was just being silly...)
> 
>
> Along those lines - is there a better way to search through an array other
> than "for (int i = 0; i < array.length; i++)"?
>

Yes, "foreach". I think Frank has covered it.
 
>
> I did look at it as a learning experience.  I was just frustrated at the
> time because I had a 700-line+ file of C# that wouldn't execute because of
> this one little problem.
>

Yeah, I know... been there :-) Nevertheless, patience is an essential part
of the learning process...
 
>
> So you put braces after the variable declaration?  That's the first time
> I've seen that structure.  :)
> 
>
> Yeah, and you code in SECTIONs too!  ;)

Touche!  (Nevertheless, my code works... :-))
>
> Of course I'm kidding - that just goes to show that different folks have
> different ideas of what "readable" is.  My biggest complaint in how much
> north-south real estate it takes up on my screen.  I guess if my methods
> were more of a proper size, I wouldn't have to scroll to see them. Maybe
> that's a corollary to the 10-line rule - if you can't see it at one time
> in the editor, it's too big!

Absolutely. Now you're getting it. Small is beautiful.
>
> (Is it double-spaced in the IDE, or was that just what happened when you
> pasted it into the newsreader?)

No, it's the  bloody newsreader. I was tempted to post in HTML but I realise
most people don't have their newsreaders configured for it.

> 
>
> Why did you use char.Parse("0") instead of just '0'?

Because '0' wouldn't work...? :-)

> 
>
> No, no cheating comment from me...  :)  I wonder if
>
> dr["element_type"].ToString().ToCharArray()[0]
>
> would do what I was trying to do there?

Why not try it and see? The empirical approach always trumps the theoretical
one... :-)

> 
>
> That makes sense to me.  It's a similar concept to a few tables we have in
> our database at work.  They hold "interface parameters", and since the
> paramaters vary for each interface, we have it broken down for each
> format.  It certainly beats reference modification...  especially when the
> next guy comes along and doesn't know that the number of days to keep
> transaction history for this interface is in columns 4-6...  :)
> 
>
> I looked at it, and I sort of understand how they did it...  I'm going to
> play with some things over the next few days.  I'll post what I find, with
> hopefully enough COBOL references that the other folks won't toss me out
> on my head.  :)
>

I strongly recommend some experimentation.
 
>
> In looking at things back and forth in writing this reply, it's starting
> to click.
>
Excellent! It will take a little time. It is a journey of many small
steps... Each method you write will be "better" than the last one.

For myself, I can see the difference in what I write today and what I wrote
even 5 ws ago. In a year, I'll probably be embarrassed by what I have and
want to rewrite the lot... :-) At this stage, as I mentioned earlier,
elegance is only of passing interest. The prime criterion is that it works.
When it works, it not only builds confidence, but it also buys time to do
further study and make the next round even better.

<remainder snipped>

Pete.



Report this thread to moderator Post Follow-up to this message
Old Post
Pete Dashwood
02-01-07 11:55 PM


Re: [OT] My First C# (warning - long post)
In-Reply-To: <52f827F1n712jU1@mid.individual.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Message-ID: <64fe7$45c29000$454920f8$6932@KNOLOGY.NET>
X-Complaints-To: abuse@usenetserver.com
Organization: UseNetServer.com
Lines: 105
X-Trace: 64fe745c29000e0ec855d06932
Xref: number1.nntp.dca.giganews.com comp.lang.cobol:162986

Frank Swarbrick wrote:
> LX-i<lxi0007@netscape.net> 02/01/07 7:51 AM >>> 
>
> I'm not sure specifically what you are referring to, but, if we assume the
> above code is something like
> string array[] = new string[10];
> for (int i = 0; i < array.length; i++)
> {
>     doSomething(array[i]);
> }

Not quite...  but close enough.

> You can replace it with
>
> foreach (string s in array)
> {
>     doSomething(s);
> }
>
> Is that what you're looking for?

Sort of.  I've been doing some digging, and had found foreach() - I also
found the DataSet's ReadXml method.  This is what I've got at the
current time...

protected DataSet keywords = new DataSet();
...
// This is executed in the constructor
protected void fillCobolKeywords() {
keywords.ReadXml("cobol_keywords.xml");
}
...
// Returns "true" if the word passed is a COBOL keyword
protected bool isCobolKeyword(String ickText)
{
bool      ick = false;
DataTable dt  = keywords.Tables[0];

foreach (DataRow dr in dt.Rows)
{
if (dr[0].ToString() == ickText)
{
ick = true;
}
}

return ick;
}

With this, though, if the keyword is "ACCEPT", it's still plowing
through 350+ entries before returning.  Could (should) I short-circuit
it and return true in the loop - something like this...

// Returns "true" if the word passed is a COBOL keyword
protected bool isCobolKeyword(String ickText)
{
DataTable dt  = keywords.Tables[0];

foreach (DataRow dr in dt.Rows)
{
if (dr[0].ToString() == ickText)
{
return true;
}
}

return false;
}

I appreciate the suggestion.  foreach is pretty  - I've used it in
PHP quite a bit.  I guess what I was looking for was an array.search
method or something that may apply a more efficient searching algorithm
than just "gimme one - is this it? nope, gimme another one - is this it?
nope..." etc.

(The only reason I'm concerned with this sort of efficiency is that this
...er... whatever it is (class/component/process masquerading as OO)
will run as part of a page post from our .NET CM site.  If I'm
rebuilding the indexes, it doesn't matter if it takes 20 seconds per
program - but in that web page, it would be unacceptable.)

Hmm....  Maybe this needs to be a separate thread...  Can an ASP.NET
page spawn a thread that runs after the response has been sent to the
user?  Sounds like I've got more digging to do....  I wish I wasn't
moving in 2 ws!  It seems like there's just too much to consider - I
guess there's got to be something for the person who comes after me to
do.  :)

--
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
~   /   \  /         ~        Live from Montgomery, AL!       ~
~  /     \/       o  ~                                        ~
~ /      /\   -   |  ~          daniel@thebelowdomain         ~
~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
~ h---- r+++ z++++                                            ~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~

"Who is more irrational?  A man who believes in a God he doesn't see, or
a man who's offended by a God he doesn't believe in?" - Brad Stine

Report this thread to moderator Post Follow-up to this message
Old Post
LX-i
02-02-07 02:55 AM


Re: [OT] My First C# (warning - long post)
In-Reply-To: <52fbl0F1o57gtU1@mid.individual.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Message-ID: <4cdef$45c296f3$454920f8$15447@KNOLOGY.NET>
X-Complaints-To: abuse@usenetserver.com
Organization: UseNetServer.com
Lines: 69
X-Trace: 4cdef45c296f3e0ec855d15447
Xref: number1.nntp.dca.giganews.com comp.lang.cobol:162989

Pete Dashwood wrote:
> "LX-i" <lxi0007@netscape.net> wrote in message
>  news:19a17$45c1fe8b$454920f8$23261@KNOLO
GY.NET... 
>
> No. Those are global variables. Click on Help in VS2005 and then click
> "index". Enter "properties"... Or start with this direct local link:

I found that.  (BTW, that's just another plus of the IDE - the F1 help
is really helpful!)
 
>
> Because '0' wouldn't work...? :-)

Must be that managed vs. unmanaged stuff...  I can assign '0' to a char
variable.  I believe you - I wonder what the difference is?

> Excellent! It will take a little time. It is a journey of many small
> steps... Each method you write will be "better" than the last one.

OK - here's what I've got for one of the methods.  I'm not sure that
this looks right...

protected DataSet itemInfo = new DataSet();
...
// Establish the element for this class instance
public void retrieveElementInfo(String reiElementId)
{
// Retrieve the information about the passed program
String sql = "SELECT * "
+ "FROM active_elements "
+ "WHERE element_id = '" + reiElementId.Trim() + "'";
SqlDataAdapter da = new SqlDataAdapter(sql, dbConn);
da.Fill(itemInfo);

if (itemInfo.Tables.Count > 0)
{
elementType    =
itemInfo.Tables[0].Rows[0]["element_type"].ToString().ToCharArray()[0];
elementSubType =
itemInfo.Tables[0].Rows[0]["element_subtype"].ToString().Trim();
fileName       =
itemInfo.Tables[0].Rows[0]["server_name"].ToString().Trim();
elementId      = reiElementId.Trim();
}
}

(We have to trim the stuff coming out of the database because it's
defined as char instead of varchar...)

--
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~
~   /   \  /         ~        Live from Montgomery, AL!       ~
~  /     \/       o  ~                                        ~
~ /      /\   -   |  ~          daniel@thebelowdomain         ~
~ _____ /  \      |  ~      http://www.djs-consulting.com     ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e    ~
~ h---- r+++ z++++                                            ~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~

"Who is more irrational?  A man who believes in a God he doesn't see, or
a man who's offended by a God he doesn't believe in?" - Brad Stine

Report this thread to moderator Post Follow-up to this message
Old Post
LX-i
02-02-07 02:55 AM


Sponsored Links




Last Thread Next Thread Next
Search this forum -> 
Post New Thread

Cobol archive

Show a Printable Version Send to friend Email This Page to Someone! subscribe to this thread Receive updates to this thread
Computer Consultants
Programming Jobs
Visual Basic Controls
SQL Server Programming
Webservices
Java Security
Visual Studio
C# Programming
Visual J++
Software engineering
Open source Software
Perl Programming
PHP Programming
ASP Programming
ASP .NET Programming
Visual Basic Programming
Windows Scripting Host
Java Programming
Java Help
Java Beans
VBScript
Cobol
MAC Applications
Unix Programming
Forum Jump: