Experimenting with SDC/Tcl wildcards: Quartus TimingQuest Timing Analyzer

Wildcards

There is a certain confusion regarding how wildcards are matched in the SDC file (in fact, by the Tcl commands), which is why full paths are often used. This causes overloaded SDC files that don’t survive changes in the hierarchy.

For example, regarding get_pins, the SDC and TimeQuest API Reference Manual page 2-15 states that pipe characters (“|”) are treated as special characters, and are therefore not matched against the “*” wildcard in the default mode. So by default, the full path has to be given, except for specific strings within hierarchies.

The -hierarchical flag somewhat helps by allowing relative names (skip the beginning of the path).

For a classic Tcl match, where ‘*’ can match a pipe character, use -compatibility_mode.

But what about get_clocks?

Experimenting

One significant advantage of Tcl scripting over Xilinx’ UCF is that one can try out the expressions in a Tcl shell. Some basics can be found in page 3-17 of the Quartus II Handbook, vol.1, chapter 3.

More inspiration can be taken from the examples in the SDC and TimeQuest API Reference Manual. It may also be helpful to look at the Quartus II Scripting Reference Manual.

From the command line, using the “-s” flag:

$ quartus_sta -s

After the welcome note, open the project (after fitting) and create a timing netlist:

tcl> project_open myproject
tcl> create_timing_netlist
tcl> read_sdc
tcl> update_timing_netlist

for effectively opening myproject.qsf. The two latter are required for get_clocks to work. One can go e.g.

tcl> get_clocks -long_help

to get some help (same text as in the manuals).

It’s possible to test what matches which command. For example, to list the PLL-derived clocks (based upon the signal’s name):

tcl> set mypins [ get_pins -compatibility_mode *|divclk ]
tcl> foreach_in_collection pin $mypins { puts [get_pin_info -name $pin] }

The Tcl shell will print something like “_col0″ in the middle to indicate that a collection has been set up. This collection is accessed through $mypins. The second command prints the matched pins to the console.

Or for those who prefer one-liners (all pins on top-level):

tcl> query_collection -all [ get_pins * ]

The “-all” flag overrides the default limit of 20 elements. To have each printed on a separate line,

tcl> foreach i [ query_collection -all [ get_pins -hierarchical * ] ] { puts "Pin: $i" }

The -hierarchical flag is important. Without it, only the toplevel pins are given (even for just [ get_pins ]). Counterintuitive, but nevertheless true. The -compatibility_mode flag is also fine (used a lot in this post) but is Quartus specific.

The counterpart for “-all” is “-limit 1″, which fetches only the first element.

So what about get_clocks?

Listing all clocks in the design on separate lines:

tcl> foreach i [ query_collection -all [ get_clocks ] ] { puts "$i" }

Or use foreach_in_collection:

tcl > foreach_in_collection i [ get_clocks ] { puts [ get_clock_info $i -name ] }

Note that get_clock_info can obtain information other than just the name.

Alternatively, use “join” instead of “foreach”:

tcl> join [ query_collection -all [ get_clocks ] ] "\n"

If nothing is printed, and instead it says

Warning (332173): Ignored filter: * could not be matched with a clock

it’s most likely because read_sdc and update_timing_netlist haven’t been issued, as mentioned above.

tcl> foreach i [ query_collection -all [ get_clocks *|vga_pll|*|divclk] ] { puts $i }

which, surprisingly enough worked in the convenient way: The wildcards matched pipe characters, so one can, in fact, use this simple format in SDC files, e.g.

set_false_path -from [get_clocks *|vga_pll|*|divclk] -to [get_clocks *|bus_pll|*|divclk]
set_false_path -from [get_clocks *|bus_pll|*|divclk] -to [get_clocks *|vga_pll|*|divclk]

for setting up false paths between two clocks that are derived from a common reference with PLLs, the wrong way.

The correct way is with set_clock_groups, but that’s not what this post is about… And by the way, Quartus doesn’t have a shortcut to include derived clocks in set_clock_groups, like in Vivado. So the PLLs’ output clocks must be named explicitly (but wildcards help).

Getting all kind of info

If we’re at it, all kind of info can be obtained on cells in the design. For example, the location of certain instances in the design (pins etc. can also be obtained with different parameters to get_cell_info):

foreach_in_collection cell [ get_cells -compatibility_mode *rx_pma.rx_cdr] { puts "[get_cell_info $cell -location ]: [get_cell_info $cell -name]" }

QSF scripting

Pointing at specific cells by virtue of expressions works within a script, but not in the QSF file. For example, this works as a script

set_instance_assignment -name CDR_BANDWIDTH_PRESET High -to [ get_cells -compatibility_mode *|xcvr_inst|*rx_pma.rx_cdr]

but fails in a QSF file.

It’s possible to retrieve the already existing assignments. Try

tcl> get_instance_assignment -help
tcl> get_all_assignments -long_help

The latter gives some interesting examples on scanning existing assignments. In particular, turning one of the examples into a (very long) one-liner, once can go

tcl> foreach_in_collection asgn_id [get_all_assignments -type instance -name *] { set from [get_assignment_info $asgn_id -from] ; set to [get_assignment_info $asgn_id -to] ; set name   [get_assignment_info $asgn_id -name] ; set value  [get_assignment_info $asgn_id -value] ; puts "$name ($from -> $to) = $value" }

in order to list all instance assignments (i.e. echo the QSF’s assignments).

Same for all global assignments (and there are many):

foreach_in_collection asgn_id [get_all_assignments -type global -name *] { set entity [get_assignment_info $asgn_id -entity] ; set name [get_assignment_info $asgn_id -name] ; set value  [get_assignment_info $asgn_id -value] ; puts "$entity: $name = $value" }

Not clear what it’s useful for, but anyhow

Running a nested X-Windows server

Why?

It’s sometimes desired to run an X-Windows program in a separate “screen” but not actually have another screen. The expensive way is to bring up a whole virtual server. But if it’s fine to run the program on the same computer, all we want is to have a window, in which the program is confined.

This is handy if the program has a tendency to steal focus with popups all the time.

It’s also useful for opening windows from a remote machine, and the regular X server refuses despite being generous with “xhost +”. The nested server isn’t picky with who it’s hosting.

Some installations

First, install Xnest if it’s not already installed, e.g. (as root)

# yum install Xnest

It’s also possible to install a very simple (and somewhat yucky) window manager

# yum install twm

Action

Then open a new window, which turns into a new X server:

$ Xnest -s 0 -ac :1 -geometry 1900x1020+5+0&

The dimensions given by the “geometry” flag are those making a full screen coverage on my monitor. This varies, of course.

Launch a Window Manager and a terminal window in the new X server. The former is necessary to make windows movable, resizable, etc.

$ twm -display :1
$ DISPLAY=:1 gnome-terminal &

Note that apparently nothing happens after launching the first command, because there are no clients in the Xnest window.

And then use the terminal to run applications inside the nested X-window server.

twm too yucky?

The Gnome Window Manager can be used instead of the command issuing twm:

$ DISPLAY=:1 gnome-wm &

The reason not to use Gnome’s window manager is that it allows minimizing windows. If that is done accidentally, the window is lost (unless a bottom panel is generated, which starts to get a bit messy for a simple task).

 

A ghost process eating up all RAM?

After a “find” operation spanning the entire disk, I suddenly had System Monitor (2.28.0 of Fedora 12) telling me that 11.5 GB out of the existing 16 GB were used up, and the applet said 75% was “in use by programs”. Really. Virtually nothing was running on the system.

Just to be sure, I tried out

$ ps aux --sort -rss | less

(list processes sorted by resident memory) and as expected, no memory hog to be seen.

So what does the kernel (a home cooked 2.6.35.4) say for itself?

$ cat /proc/meminfo
MemTotal:       16463436 kB
MemFree:          130568 kB
Buffers:         2818532 kB
Cached:          1387344 kB
SwapCached:            0 kB
Active:          3368176 kB
Inactive:        2246912 kB
Active(anon):    1407872 kB
Inactive(anon):   339276 kB
Active(file):    1960304 kB
Inactive(file):  1907636 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:               368 kB
Writeback:             0 kB
AnonPages:       1409264 kB
Mapped:           174032 kB
Shmem:            337932 kB
Slab:           10246976 kB
SReclaimable:    9526744 kB
SUnreclaim:       720232 kB
KernelStack:        5112 kB
PageTables:        47880 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8231716 kB
Committed_AS:    4241756 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      122564 kB
VmallocChunk:   34359572612 kB
HardwareCorrupted:     0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      350080 kB
DirectMap2M:    16422912 kB

Hmmm… That’s the kernel eating up ~10 GB, most of which is reclaimable. This page seems to explain the issue: As the disk was scanned, directory and inode metadata was probably cached. So what if that takes nearly 10 GB?

The thing is that it gives a somewhat misleading picture of the computer’s state.

So let’s just tell the kernel to drop all those caches, as suggested in that page:

As root, just go

# echo 3 > /proc/sys/vm/drop_caches

and watch how the memory meter drops. This problem is supposed to be solved in kernel not as ancient as mine.

Gnome 2 failing to load an Applet for no apparent reason

Fedora 12: It started with some error message about something crashing, and the Workspace Switcher applet was gone.

I tried re-adding it to the panel, but I got an error window saying that the panel encountered a problem while loading “OAFIID:GNOME_WorkspaceSwitcherApplet”. And offered me to delete it from the panel. Or not delete it. Nothing helped. Even not restarting compiz.

I took a look in the panel configuration directory, just to find that there were multiple instances of the same applet:

$ grep -r GNOME_WorkspaceSwitcherApplet ~/.gconf | sort

.gconf/apps/panel/applets/applet_0/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_10/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_11/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_12/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_13/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_15/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_16/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_5/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_6/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_7/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_8/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue>
.gconf/apps/panel/applets/applet_9/%gconf.xml:        <stringvalue>OAFIID:GNOME_WorkspaceSwitcherApplet</stringvalue

In a normal setting, there are three lines here (why? Never mind).

The solution was surprisingly simple. Just find the process with the name gnome-panel. And kill it (with a plain kill, no special signal is necessary).

$ killall gnome-panel

The panel disappears reappears promptly. Maybe with duplicate applets, but hey, it finally works!

Linux kernel version magic: Adding the missing plus suffix

Trying to insmod a kernel module, which was just compiled against the true headers of the running kernel, I got:

# insmod mymodule.ko
insmod: error inserting 'mymodule.ko': -1 Invalid module format

And this in /var/log/syslog:

mymodule: version magic '3.3.0-xxx SMP preempt mod_unload ARMv7 ' should be '3.3.0-xxx+ SMP preempt mod_unload ARMv7 '

Really? Are you picking on me? Rejecting my module just because of a missing plus sign?!

The plus sign is there in the first place because the kernel was compiled with a git repository, which displayed modifications relative to the official tree. To avoid it, I could have compiled the kernel after renaming the .git directory to something else prior to compiling the kernel. But I forgot to do that.

In fact, I should have turned kernel magic versioning off altogether.

The plus sign is absent in the current kernel headers, because they were generated without the git repository (natively on the target). Hence the difference.

One could use modprobe –force, but isn’t it nicer to just get the version magic right?

This solution holds for the 3.3.0 kernel, but probably works on others as well.

The file you want to edit is /usr/src/kernels/{your version}/include/generated/utsrelease.h and just add the ‘+’ sign to the end of the version number. E.g.

#define UTS_RELEASE "3.3.0-xxx+"

And now all modules compiled against the kernel will load with no issues.

For those interested in the gory details: It’s mymodule.mod.c that is responsible for supplying the version magic. It’s compiled into mymodule.mod.o, and then fused together with mymodule.o to become mymodule.ko. This is what the famous “MODPOST” compilation stage does (in fact, it’s a make -f on scripts/Makefile.modpost, which in turn calls scripts/mod/modpost).

mymodule.mod.c gets the number by including linux/vermagic.h (actually, it includes other similar files as well) which in turn includes generated/utsrelease.h, which supplies the version magic explicitly.

Updating time zone information on a Linux machine

Since daylight saving time is an issue for political dispute in Israel, the time of switching back and forth changes all too often. To keep my computer on track, I need to update the timezone info file every now and then.

There are a lot of tutorials on the web about this, for example these two. Here’s a quick summary:

Check the current situation. Is the timezone file in sync with the real world?

$ zdump -v /etc/localtime | less

Ah, so it isn’t. Go to IANA’s site and download the data file (e.g. tzdata2013d.tar.gz). From within that bundle, fetch the file named “asia”. And go:

$ zic -d tmpdir asia

which creates a new directory, tmpdir, with several zone files inside.

Unfortunately, trying to run zdump on just a file doesn’t work very well. So I went to /usr/share/zoneinfo and removed the file called Israel as well as Asia/Jerusalem and Asia/Tel_Aviv, and the /etc/localtime as well. They were all the same, identical file.

Then copied tmpdir/Asia/Jerusalem into /usr/share/zoneinfo/Asia and

# ln -s /usr/share/zoneinfo/Asia/Jerusalem localtime

Plus, in /usr/share/zoneinfo/Asia, just to be safe:

# ln -s Jerusalem Tel_Aviv

and in /usr/share/zoneinfo:

# ln -s Asia/Jerusalem Israel

And a final check (same as before)

$ zdump -v /etc/localtime | less

A machine reboot may be in place to make all programs catch up with the new data. Or just restart key programs, if it doesn’t matter all that much.

Just to be 100% sure that the change is in effect, a one-liner script can be used. For example how is GMT time vs. local time compare 48 days from now?

$ perl -e '$t=time() + 86400*48; print scalar gmtime($t)." --> ".scalar localtime($t)."\n";'

Side notes: The sources for zic and other utilities are available next to the data file on IANA’s site. But any sane Linux distribution should have these installed already. Or at least at the repository. Also worth to note, that the syntax of these data files is pretty cool: It’s not just dates, but political rules.

 

Drupal 7: Making a global regular expression replacement

The goal: Create spam-harvesting safe mailto links anywhere in the pages, generated on the fly with slightly obfuscated JavaScript, so that harvesting bots don’t get the email addresses. To make it slightly more complicateded, I want a replacement pattern with a parameter, telling the replacement script which email address to inject.

In other words, if I wrote %mail{1}% somewhere in the page’s source, that is replaced by the second email address in a known list of addresses.

Of course there the Token module. But I wanted the replacement to depend on the token string. Globally.

I use arthemia, so this appears everywhere in the paths to files.

Bad attempt #1

I thought that dvessel’s suggestion on a pretty old page would do the job (and it looks like it was obvious to everyone which file to edit, sites/all/themes/arthemia/template.php). But that suggestion was good for Drupal 5.

The theme I used, arthemia, already has an arthemia_preprocess_page() function, but not an arthemia_render_template(). I followed the suggestion, and nothing happened, of course. Drupal 7 doesn’t look in that direction.

Bad attempt #2

There is this golden rule in Drupal, that you don’t edit the core functions. Well, well, it was time to break it again. This time with the core of the core: include/common.inc, modifying drupal_render. Yup, I couldn’t have broken that rule harder. But after a few hours of the regular Drupal ceremony of reading a lot of useless tips on the web, I thought it was best to just get the job done.

The main problem was that all hooks are related to a certain type of elements. There is no hook for “just before the HTML is handed over to the browser”. Or that’s the impression I got.

First, I added the script I wanted included in every page. It would prefer it to be in the <head> section (because that’s usually where global scripts are) and I would prefer it to be a piece of content. But again, hours of looking for the “Drupal” way to do it, I just added the following to the top of sites/all/themes/arthemia/page.tpl.php:

<script language="JavaScript">
<!--
function myfunction(i) {
 [ ... ]
}
-->
</script>

It’s an ugly solution, but it gets the job done. I could, in theory, plant it as the content of an unused part of the page, and then mangle the page’s structure as it was being processed. Too much work for the cute shortcut of altering the script from Drupal’s interface.

And now to finding the markups, and make them run the function above. Using the preg_replace_callback() function, render_template was edited to this in the end of the function (just before “return $output”):

// Mangle
 $output = preg_replace_callback("|%mail\{(\d+)\}%|",
   function ($matches) {
     return "<script language=\"JavaScript\">\n<!--\nmyfunction($matches[1]);\n-->\n</script>";
   },
   $output)

That worked well. Actually, too well. The replacement took place also in editing boxes, so the original markup text couldn’t be edited.

The correct way

OK, so I took one step back. Let’s use the regular hooking mechanism, after all, and define the hooks for the content and the footer. Good enough. And as a side effect, the core is left intact, as I only edit the theme’s page template file.

So instead of the changes above I added this to the top of sites/all/themes/arthemia/page.tpl.php:

<script language="JavaScript">
<!--
function myfunction(i) {

 [ ... ]
}
-->
</script>

<?php
function mail_post_render($content, $element) {
  $content = preg_replace_callback("|%mail\{(\d+)\}%|",
    function ($matches) {
      return "<script language=\"JavaScript\">\n<!--\nmyfunction($matches[1]);\n-->\n</script>";
    },
    $content);

 return $content;
}

if ($page['content']) {
 $page['content']['#post_render'] = array('mail_post_render');
}
if ($page['footer']) {
 $page['footer']['#post_render'] = array('mail_post_render');
}

?>

And that finally worked in a sane manner: The footer and content were mangled, and I was still able to edit the original text. Hurray!

As usual, a simple task took a full day to complete. Welcome to the wonderful world of Drupal.

Resetting a Windows XP/7/8 password, the Linux way

What happens if a Windows user loses his or her password? No problem, Windows was never meant to be secure. Only appear as if it was.

There are several automatic tools out there. I preferred running my Fedora-based LiveUSB and fix it while actually seeing what I’m doing. The whole thing is about modifying the SAM file used on authentication.

Note that the flow shown below failed. What did work, eventually, was unlocking the Administrator account, which doesn’t have any password to begin with. Why I failed to reset a user’s password is beyond me. Maybe because it had administrator’s privileges? Maybe because it was Windows 8?

Anyhow, first I installed chntpw. It’s an offline registry editor it says somewhere, but I never checked that.

# yum install chntpw

Following this guide, mount the partition and change directory to where the SAM file is (Windows/System32/config, like any NT machine). Note the capital letters in Windows and System32.

Then go (possibly as root)

$ chntpw SAM
chntpw version 0.99.6 080526 (sixtyfour), (c) Petter N Hagen
Hive <SAM> name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 666c <lf>
Page at 0x6000 is not 'hbin', assuming file contains garbage at end
File size 262144 [40000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 222/17400 blocks/bytes, unused: 14/2920 blocks/bytes.

* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0
| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrator                  | ADMIN  | dis/lock |
| 01f5 | Guest                          |        | dis/lock |
| 03e9 | myself                         | ADMIN  | dis/lock |

---------------------> SYSKEY CHECK <-----------------------
SYSTEM   SecureBoot            : -1 -> Not Set (not installed, good!)
SAM      Account\F             : 0 -> off
SECURITY PolSecretEncryptionKey: -1 -> Not Set (OK if this is NT4)
Syskey not installed!

RID     : 0500 [01f4]
Username: Administrator
fullname:
comment : Built-in account for administering the computer/domain
homedir : 

User is member of 1 groups:
00000220 = Administrators (which has 2 members)

Account bits: 0x0211 =
[X] Disabled        | [ ] Homedir req.    | [ ] Passwd not req. |
[ ] Temp. duplicate | [X] Normal account  | [ ] NMS account     |
[ ] Domain trust ac | [ ] Wks trust act.  | [ ] Srv trust act   |
[X] Pwd don't expir | [ ] Auto lockout    | [ ] (unknown 0x08)  |
[ ] (unknown 0x10)  | [ ] (unknown 0x20)  | [ ] (unknown 0x40)  | 

Failed login count: 0, while max tries is: 0
Total  login count: 10

- - - - User Edit Menu:
 1 - Clear (blank) user password
 2 - Edit (set new) user password (careful with this on XP or Vista)
 3 - Promote user (make user an administrator)
 4 - Unlock and enable user account [probably locked now]
 q - Quit editing user, back to user select
Select: [q] > q

This shows a lot of info, including the list of users. The point is to reset a specific user. Changes made like this will affect all users.

To get just the list of users,

$ chntpw -l SAM
chntpw version 0.99.6 080526 (sixtyfour), (c) Petter N Hagen
Hive <SAM> name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 666c <lf>
Page at 0x6000 is not 'hbin', assuming file contains garbage at end
File size 262144 [40000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 222/17400 blocks/bytes, unused: 14/2920 blocks/bytes.

* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0
| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrator                  | ADMIN  | dis/lock |
| 01f5 | Guest                          |        | dis/lock |
| 03e9 | myself                         | ADMIN  | dis/lock |

And now let’s modify only one user in the list

$ chntpw -u 'myself' SAM
chntpw version 0.99.6 080526 (sixtyfour), (c) Petter N Hagen
Hive <SAM> name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 666c <lf>
Page at 0x6000 is not 'hbin', assuming file contains garbage at end
File size 262144 [40000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 222/17400 blocks/bytes, unused: 14/2920 blocks/bytes.

* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0
| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrator                  | ADMIN  | dis/lock |
| 01f5 | Guest                          |        | dis/lock |
| 03e9 | myself                         | ADMIN  | dis/lock |

---------------------> SYSKEY CHECK <-----------------------
SYSTEM   SecureBoot            : -1 -> Not Set (not installed, good!)
SAM      Account\F             : 0 -> off
SECURITY PolSecretEncryptionKey: -1 -> Not Set (OK if this is NT4)
Syskey not installed!

RID     : 1001 [03e9]
Username: myself
fullname:
comment :
homedir : 

User is member of 1 groups:
00000220 = Administrators (which has 2 members)

Account bits: 0x0214 =
[ ] Disabled        | [ ] Homedir req.    | [X] Passwd not req. |
[ ] Temp. duplicate | [X] Normal account  | [ ] NMS account     |
[ ] Domain trust ac | [ ] Wks trust act.  | [ ] Srv trust act   |
[X] Pwd don't expir | [ ] Auto lockout    | [ ] (unknown 0x08)  |
[ ] (unknown 0x10)  | [ ] (unknown 0x20)  | [ ] (unknown 0x40)  | 

Failed login count: 2, while max tries is: 0
Total  login count: 1

- - - - User Edit Menu:
 1 - Clear (blank) user password
 2 - Edit (set new) user password (careful with this on XP or Vista)
 3 - Promote user (make user an administrator)
 4 - Unlock and enable user account [probably locked now]
 q - Quit editing user, back to user select
Select: [q] > 1

Hives that have changed:
 #  Name
 0  <SAM>
Write hive files? (y/n) [n] : y
 0  <SAM> - OK

In this case it clears the password (the choice of “1″). In fact, it appears like the password was already cleared when I captured this log, but it did no good.

As mentioned above, the password was still required after this, so the operation failed. I also failed to change the password for this user.

Using perl for in-place search-and-replace

To make a long story short:

$ perl -pi.bak -e 's/this/that/g' `find inhere/ -type f`

or to delete entire lines that contain a certain substring:

$ perl -pi.bak -e 's/^.*?RUNTIME_PARAM.(?:OUTPUT|SHARED)DIR.*?[\n\r]+//gm' $(find . -iname \*.xci)

This will create backup files. Yes, you want them. Really. Otherwise, in particular under Windows, errors like this may show up:

Can't do inplace edit on inhere/example.c: Permission denied.

This may look harmless, but in fact the target file ends up complete deleted. So don’t go just perl -pi -e. It may go horribly wrong.

Another thing to watch out for is having the .git subdirectory included in the “find” statement. In particular, “find .” may lead to this. Messing up the git repository is no fun.

The in-place execution runs separately on each line, so it’s not useful for replacing things that span across more than one line. In that case, use the -0777 flag to enable slurp mode (see man perlrun), e.g.

$ perl -0777 -pi.bak -e 's/\n\n/\nAAAA/g' thefile.txt

Or as an ugly alternative, use a “full” perl script should be used. For example, in order to remove multiple blank lines from C sources,

$ for i in *.c *.h ; do perl -e 'local $/; $a=<>; $a=~s/\n{3,}/\n\n/g; print $a;' < $i > $i.new; mv -f $i.new $i; done

This removes any occurrence of three or more newlines into two. It’s fine to have an empty line, but not more than one.

Finding a function / method in a large C/C++ project

So there’s this huge pile of source code, with an enormous amount of functions and methods. How can you quickly find where each is defined? IDEs has this functionality built in, but it’s not so easy to push an already existing (and huge) project into an IDE.

The solution is so simple. For example,

$ ctags -f sourcemap -R OpenCV-2.4.0/

which will scan the OpenCV-2.4.0 directory for source file, parse them, and create a textual file, sourcemap, with (probably) all method and function definitions listed in alphabetical order. With the files they were found in. The format isn’t very human-friendly, but still quite easy to find the answer in.