• Linux
  • October 2018
    M T W T F S S
    « Sep    
  • Meta

  • Follow me on Twitter

  • Advertisements

Lack of Linux



FnLoC v2.2

I’m not certain what version the program really is. I’d made several modifications to the original program some 20 years ago and apparently some of the early source code is missing. I know there was once a version 1.3 that listed the functions in the same order as they appeared in the target source code.

The last version was dubbed version 2.1.2 and since the code I finished today is so much different, I decided to make it 2.2. Maybe there’s enough difference to make it a major revision and call it 3.0. I don’t know.

I did some research and refreshed my knowledge of linked lists. Once I felt reasonably comfortable with them, I set out to implement a singly linked list to replace the stack. The primary motivation was to list functions in the output in the same order as they appeared in the target source code file. Using a stack (first in, last out), the functions were listed in reverse order.

A side benefit was that I needed fewer functions to implement the linked list since all I needed to do was to add data to the end of the list , display the output, and then free the memory when I was done.

In process of implementing the list, I simplified my data structures for holding the function data. Instead of a struct containing the data in main(), I used a couple of simple variables to hold the data until it was put into the list. Much easier to manage.

Most of the code for parsing a line of code and determining states was left intact since it was already working well. I did tweak the code for determining the possible states a function could be in because, for some reason, it would sometimes display main() with name of the next function encountered. The count would be right but the name would be wrong. Fixing the problem was a matter of changing one if condition. I’d been suspicious of that line for a while.

Finally, I split up the function that displayed the data in to three different functions, based on the the information they displayed. One prints a header to identify the program and display some introductory information. Next came the function that displayed the function data, if any. Finally, there was the function that printed a summary of the counts.

After testing it, I updated the documentation and the installation package (.tar.gz). The next step is to compile it in Windows and update the Windows package. I should be able to translate the Bash script that redirects the output to a text file into a Windows batch file without too much trouble.

Do I really want Linux to be mainstream?

Lately, I’ve viewed a lot of videos on YouTube about why Linux is more dominant on the desktop. Most of them seem to cover pretty much the same ground. Among the common reasons given are:

  • Too many distributions and desktop environments to choose from
  • A lack of standardization for Linux desktop environments
  • Lack of presence in the marketplace, particularly in retail outlets
  • Users don’t want to install their own operating systems
  • Difficult to use, high learning curve, change in work flow
  • Fear of the command line or the perception that the CLI is outmoded
  • Perception that Linux users are geeks and technically inclined
  • Lack of applications and games
  • Little corporate organization and sponsorship
  • Little effort/interest in the Linux community to make it mainstream

There are other reasons but these are the ones that immediately come to mind. I’d like to address them individually.

1. Too many distributions and desktop environments to chose from. I see having a multitude of choices as a positive. With Windows and Mac you essentially only have one choice. With Linux, you can use the distribution and desktop of your choice. If the one you choose doesn’t suit you, you can change it and if you set up your system right, you can make the change without losing your data. You can usually install a Linux distribution and be up and running in less than 30 minutes. It can be difficult to decide on a distribution so do some research. Download some distros, load them onto USB drives and try them out in a live environment from the USB drive. Or find yourself an old computer and test things out on that.
2. A lack of standardization for Linux desktop environments. I don’t see this as a big problem. The Linux kernel is standardized and while there are a few niche desktop environments, there are a few common ones such as XFCE, MATE, Gnome, Cinnamon, and Unity. There may be subtle differences in the way each of them work in different distributions, but they provide pretty much the same basic functionality. I don’t really see a need for a “standardized” desktop. I like the variety that’s available and having choices. Windows and Mac each have their own standardized desktop and and if you don’t like them, you’re stuck with them.
3. Lack of presence in the marketplace, particularly in retail outlets. This is a problem. The computer manufacturers don’t push Linux systems. Many of them have long-standing relationships with Microsoft and they don’t see enough demand for Linux on the desktop to push Linux. Some manufacturers do offer Linux as a choice in their on-line sales but they don’t go out of their way to promote it. There are a few companies that specialize in building Linux systems but it’s a niche market and their products tend to be a little pricey.
4. Users don’t want to install their own operating systems. That’s understandable. They want to buy a computer and have it work right out of the box. They’re not interested in getting inside the box and tinkering with things. I get that. I happen to enjoy installing my own operating systems. I’ve been doing it since I started messing with computers – MS-DOS, many versions of Windows, and several Linux distributions, but that’s me. Sometimes it’s been a real pain in the butt.
5. Difficult to use, high learning curve, change in work flow. These are common perceptions and there is some truth to them. Linux has gotten much easier to use over the past several years. It takes some getting used to and you’ll have to unlearn some things and learn some new things. Linux doesn’t work like Windows or Mac OS and the applications you’ll use won’t work exactly the same as what your used to. Let’s face, a lot of people don’t like to learn new things and they like to stick with what’s familiar.
6. Fear of the command line or the perception that the CLI is outmoded. I hear this a lot, even from Linux users. In many distributions, you can do almost everything you need to do from a GUI and rarely, if ever, have to use the command line or a terminal. On the other hand, the command line can be your friend and is not something to be feared. A lot can be accomplished in the terminal either form the command line or through scripts that would be cumbersome and time consuming in a GUI. Even in Windows there are tasks that are best handled in a terminal.
7. Perception that Linux users are geeks and technically inclined. This is not as true as it once was. You don’t have to be a geek or a technical person to use Linux any more. For many non-technical Linux users, it just works and it works on older hardware.
8. Lack of applications and games. That’s rapidly changing. For most tasks there is an application to do it. It probably won’t have the look and feel or do everything the corresponding Windows application does and you may have to change your work flow a bit. I’m not a gamer but more games are being ported to Linux all the time.
9. Little corporate organization and sponsorship. For the most part, Linux is the work of communities of developers and users. There are a few Linux corporate entities but nothing like the monolithic giants of Microsoft and Apple. However, major corporations are getting involved in Linux and I’m not sure that’s necessarily a good thing. Overall, Linux seems to be organic in nature and I think that too much corporate intrusion, especially by companies like Microsoft and Google, will pollute the landscape. Their influence could possibly force changes in Linux that would push out smaller players, leaving us with fewer choices and more bloat and feature creep.
10. Little effort or interest in the Linux community to make it mainstream. I heard this in a YouTube video recently and I think there’s a lot of truth to it. While many in the Linux community lament that Linux isn’t mainstream, I suspect that many of us actually prefer it that way. We are the outliers, the nonconformists, the misfits, and the mavericks. If Linux were to become mainstream we’d be just like everybody else. I fear that if Linux became as mainstream as Mac or Windows, we’d all be forced into a box with only a few surviving distributions, not much different than Mac and Windows. That is a frightening thought.

I encourage the use of Linux on the desktop and I’d like to see it more widely adopted. I want people to liberate themselves from the bondage of closed operating systems and software. But people don’t like change or learning something new, even if it leads to their liberation. To quote Thich Nhat Hanh, “People have a hard time letting go of their suffering. Out of a fear of the unknown, they prefer suffering that is familiar.”

While I would very much like to see wider adoption of Linux I don’t want it to dumbed down to the lowest common denominator with only a few standardized, pedestrian, one size fits all distributions, no different than Mac or Windows.

I use Linux because it works for me and it gives me the freedom to choose how my computers will work and to configure them to meet my needs. With Linux, my computer belongs to me and it works for me. I’m not at the mercy of some monolithic corporation who decides when my operating system and my hardware are obsolete. Linux gives me control over my computers and my computing environment.

“It’s never wrong to introduce a child to Linux.”

Feelin’ the need to code

Yesterday, I felt the need to code something so I wrote a little program to convert between Celsius and Fahrenheit. Writing functions to do the conversions was easy but it took me a while to figure out how I wanted to input the data. I thought about creating prompts within the program, maybe inside a loop for multiple conversions. What I really wanted to do was get the input from command line arguments.

With a little on-line research, I figured out how to get a number from the command line using strtol() and strtod() and using the results of those functions to determine the validity of the return value.

To get the temperature scale (Celsius or Fahrenheit) to convert from, I started off using the tests I used in FnLoC to call the help function and expanded on it to call the appropriate conversion functions. That resulted in a cumbersome set if nested if-else statements but it worked.

I took another look at the program and decided that replacing the nested if-else statements with a switch() would be better. I created a local variable to hold the command line argument and passed the first character of the string to switch(). If that character isn’t f, F, c or C, it defaults to printing an error message and calling up the help function to show the proper syntax.

It’s a rather mundane and basic program but it was a learning experience and a step forward in relearning the language.

The program has 60 lines of code with 52 lines in four functions (including main). The other eight lines are compiler directives (#include) and function declarations.


FNLOC – Counting Code

As I’ve noted in recent posts and tweets, my interest in C coding has been revitalized. A couple of weeks ago I found some source code from my college Computer Science and Computer Engineering courses. Of particular interest were my programs that counted lines of code in C source files. I re-entered the code, compiled it and started working with it and studying it.

As I recall the original class assignment was to write a program (loc.c) that simply counted lines of code, ignoring comments and blank lines. The follow-up to that assignment was to enhance the original program (fnloc.c) to identify functions and count the lines of code within them.

The program’s output is a listing of all the functions with their respective lines of code and then a summary showing how many functions it finds and the total lines of code in functions, how many lines of code located outside functions (compiler directives and global declarations), and the total number of lines in the code. I found the second program useful and I made a few minor modifications to it even after the class concluded.

After resurrecting the code I found myself trying to understand how the code works and the logic behind it. I ran the program against various source files and compared the results with my manual code counts. I found discrepancies between the counts and started looking at the code to see why some lines of code weren’t being counted correctly. See Revisiting Old Code and the accompanying comments for more details.

I created README and CHANGELOG files for the program to detail pertinent information and create a chronological history of the changes. I also read up on C code styling standards and formalize the style I use which is predominantly what Kernighan and Ritchie used in The C Programming Language, 2nd Edition along with some sage advice from Linux Kernel Coding Style by Linus Torvalds. Naturally, my style works well with my program. But nearly any C source file written in the K&R style should work.

I’ve corrected most of the problems I’ve discovered but there are a few limitations and requirements.

Functions should be written in the following general format:

int function(int x)
    body of function

Data structures and array definitions (unless they fit on a single line) should have a format similar this:

struct {
    int len;
    char *str;
} *p;

Essentially, any line where an open brace is the first character of the next non-blank line will be processed as a function.

Conditional statements and for loops without an opening brace a the end of the line will be counted as a single line of code once and ending semi-colon is reached. Each of the following examples are seen as single lines of code:

if (condition)

for (i=1; i < 10; i++)
    if (condition)

if (condition) {

In the last example, the if (condition), action1, and action2 are separate lines of code. The else action3 is seen as one line of code.

For now, I’m considering this to be acceptable behavior. In my mind, I can see each of those constructs as single logical lines of code. I can live with that.

I’ve tried several different things to force the program to see each line containing code as a line of code but so far none of them have worked. The code, as written, seems like it should recognize the above constructs as multiple code lines but it doesn’t. It’s been over 20 years since I wrote the original code so my understanding of how it works may not be as clear as it was then. For that matter, it’s possible that I may not have fully understood it then either.

My renewed interest in writing code is mostly for my own enjoyment and to keep my mind active. Around the time I dropped out of the Computer Science program, it had become tedious but that was probably because at that point, I was only taking one class at a time and it was difficult to recall when I’d taken the prerequisite classes, let alone what I might have learned in them.

I don’t think I ever really lost my interest in writing code. Since then I’ve worked with HTML and CSS, DOS batch files and Powershell, and, for the last couple of years, Bash scripts. Generally, I’ve done them in the pursuit of my own interests or to accomplish a particular task with no pressure to produce anything or meet anyone’s expectations.

Linux is user friendly


Revisiting Old Code

I recently found some of my C programming books, reviving my interest. It’s been nearly 20 years since I’ve written any source code and I’m quite rusty. A couple of my books and the copy of The C Programming, Second Edition by Kernighan & Ritchie were written in the late 1980s and early 1990s and many of the example program listings don’t conform to modern C standards which makes relearning C a bit more challenging. It also doesn’t help that I don’t remember much from my programming classes and such.

I happened to find a notebook contain some of the source code I wrote as a student. Much of that code no longer makes much sense to me, largely because I’m no longer familiar with the mathematical problems they were meant to solve and I don’t remember much about C data structures either.

I did find my source code for a program I wrote that reads a text file of C or C++ source code and counts how many lines of code it contains disregarding comments and blank lines, and displays the result.

I later modified the program to identify functions and count their lines of code. This program listed all of the functions and their respective counts, then displayed a summary of the total number of functions, total lines of code contained in functions, and total lines of code for the program.

I haven’t been able to locate the original source files so I’ve been typing them into an editor from my printed source code. I’m very prone to making typographical errors so proofreading and fixing the code can get tedious. It’s fortunate that I had the foresight to thoroughly document the original code to include function descriptions, parameters, outputs, possible side effects and limitation. I think I made three versions of the second program but I can only find the source for the first two versions.

I got the program that simply counts the lines of code (loc.c) compiles and it works. I even made a couple modifications to the displayed output. I entered the code for the second version of the function counting program (fn_loc.c) and got it to compile. However, I immediately get a segmentation fault when I try to run it. I know that it worked when I wrote it 20 years ago. I used it to print out summaries of the programs in my notebook.

The fn_loc.c program uses a stack to store a simple data structure containing the name of each function and its lines of code count and that’s where I suspect the problem lies. It’s probably a misplaced pointer.

I did a little research on debugging and recompiled the code with the debugging information included:

$ gcc -ggdb -Wall -o fn_loc fn_loc.c

Without even running the gdb debugger, the compiler’s output pointed me to the line containing my error in the function that created the stack:

s – (STACK)malloc(sizeof (struct node));

The error was obvious. The ‘-‘ should have been ‘=’. The stack was never created and the variable ‘s’ was never initialized. I corrected the error, recompiled it, and the program ran perfectly.

The compiler showed another error that I don’t quite understand:

fn_loc.c: In function ‘main’:
fn_loc.c:103:5: warning: enumeration value ‘NewLineNC’ not handled in switch [-Wswitch]

NewLineNC is one of the enumerated type values I created to track the state of the line being examined. It’s used as a transitory state in several of the functions that determine the new state after a character has been examined. I don’t seem to have an need for in in main().

That program was one of the more useful programs I wrote in school and I enjoyed writing it.

My renewed interest in programming is mostly for my own enjoyment, something to challenge my mind and keep it active. Of all the languages I used in school, C was my favorite and my go to language if I had a choice. I dabbled in Ada, C++, Java, Lisp, Pascal, and Visual Basic but only learned enough to complete assignments. Even C was self-taught. I spent a lot of time looking up functions in my Borland compiler manual or other reference books.

%d bloggers like this: